Merge branch 'omnipod_eros_dev' into omnipod_eros_dev_upstream_merge

This commit is contained in:
Bart Sopers 2020-05-07 21:16:36 +02:00
commit 7f2448adeb
122 changed files with 1932 additions and 2284 deletions

View file

@ -29,8 +29,7 @@ ext {
powermockVersion = "1.7.3" powermockVersion = "1.7.3"
dexmakerVersion = "1.2" dexmakerVersion = "1.2"
retrofit2Version = '2.8.1' retrofit2Version = '2.8.1'
okhttp3Version = '4.5.0' okhttp3Version = '4.6.0'
coroutinesVersion = '1.3.5'
} }
@ -165,6 +164,7 @@ android {
} }
firebaseDisable { firebaseDisable {
System.setProperty("disableFirebase", "true") System.setProperty("disableFirebase", "true")
ext.enableCrashlytics = false
} }
} }
productFlavors { productFlavors {
@ -252,9 +252,9 @@ dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs') implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.google.android.gms:play-services-wearable:17.0.0' 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.android.gms:play-services-location:17.0.0"
implementation 'com.google.firebase:firebase-core:17.3.0' implementation 'com.google.firebase:firebase-core:17.4.0'
implementation 'com.google.firebase:firebase-auth:19.3.0' implementation 'com.google.firebase:firebase-auth:19.3.1'
implementation 'com.google.firebase:firebase-database:19.2.1' implementation 'com.google.firebase:firebase-database:19.3.0'
implementation('com.crashlytics.sdk.android:crashlytics:2.10.1@aar') { implementation('com.crashlytics.sdk.android:crashlytics:2.10.1@aar') {
transitive = true; transitive = true;
} }
@ -267,7 +267,9 @@ dependencies {
implementation 'androidx.recyclerview:recyclerview:1.1.0' implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation 'androidx.gridlayout:gridlayout:1.0.0'
implementation 'androidx.percentlayout:percentlayout:1.0.0' implementation 'androidx.percentlayout:percentlayout:1.0.0'
implementation "androidx.preference:preference-ktx:1.1.0" implementation "androidx.preference:preference-ktx:1.1.1"
implementation "androidx.activity:activity:${activityVersion}"
implementation "androidx.activity:activity-ktx:${activityVersion}"
implementation 'com.google.android.material:material:1.1.0' implementation 'com.google.android.material:material:1.1.0'
implementation 'com.wdullaer:materialdatetimepicker:4.2.3' implementation 'com.wdullaer:materialdatetimepicker:4.2.3'
@ -278,7 +280,7 @@ dependencies {
implementation("com.github.tony19:logback-android-classic:1.1.1-6") { implementation("com.github.tony19:logback-android-classic:1.1.1-6") {
exclude group: "com.google.android", module: "android" exclude group: "com.google.android", module: "android"
} }
implementation "org.apache.commons:commons-lang3:3.9" implementation 'org.apache.commons:commons-lang3:3.10'
implementation 'org.slf4j:slf4j-api:1.7.30' implementation 'org.slf4j:slf4j-api:1.7.30'
// Graphview cannot be upgraded // Graphview cannot be upgraded
implementation "com.jjoe64:graphview:4.0.1" implementation "com.jjoe64:graphview:4.0.1"
@ -295,28 +297,28 @@ dependencies {
exclude group: "org.json", module: "json" exclude group: "org.json", module: "json"
} }
implementation "com.google.code.gson:gson:2.8.6" implementation "com.google.code.gson:gson:2.8.6"
implementation ("com.google.guava:guava:24.1-jre") { implementation('com.google.guava:guava:29.0-jre') {
exclude group: "com.google.code.findbugs", module: "jsr305" exclude group: "com.google.code.findbugs", module: "jsr305"
} }
implementation 'com.google.code.findbugs:jsr305:3.0.2' implementation 'com.google.code.findbugs:jsr305:3.0.2'
implementation "net.danlew:android.joda:2.10.3" implementation 'net.danlew:android.joda:2.10.6'
implementation 'org.mozilla:rhino:1.7.11' implementation 'org.mozilla:rhino:1.7.12'
implementation 'com.github.DavidProdinger:weekdays-selector:1.1.0' implementation 'com.github.DavidProdinger:weekdays-selector:1.1.0'
implementation 'com.github.kenglxn.QRGen:android:2.6.0' implementation 'com.github.kenglxn.QRGen:android:2.6.0'
implementation 'com.eatthepath:java-otp:0.2.0' implementation 'com.eatthepath:java-otp:0.2.0'
testImplementation "junit:junit:4.12" testImplementation "junit:junit:4.13"
testImplementation "org.json:json:20190722" testImplementation "org.json:json:20190722"
testImplementation "org.mockito:mockito-core:2.8.47" testImplementation "org.mockito:mockito-core:2.8.47"
testImplementation "org.powermock:powermock-api-mockito2:${powermockVersion}" testImplementation "org.powermock:powermock-api-mockito2:${powermockVersion}"
testImplementation "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}" testImplementation "org.powermock:powermock-module-junit4-rule-agent:${powermockVersion}"
testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}" testImplementation "org.powermock:powermock-module-junit4-rule:${powermockVersion}"
testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}" testImplementation "org.powermock:powermock-module-junit4:${powermockVersion}"
testImplementation "joda-time:joda-time:2.10.5" testImplementation 'joda-time:joda-time:2.10.6'
testImplementation('com.google.truth:truth:1.0.1') { testImplementation('com.google.truth:truth:1.0.1') {
exclude group: "com.google.guava", module: "guava" exclude group: "com.google.guava", module: "guava"
exclude group: "com.google.code.findbugs", module: "jsr305" exclude group: "com.google.code.findbugs", module: "jsr305"
@ -337,24 +339,24 @@ dependencies {
implementation "com.squareup.retrofit2:converter-gson:$retrofit2Version" implementation "com.squareup.retrofit2:converter-gson:$retrofit2Version"
// Phone checker // Phone checker
implementation 'com.scottyab:rootbeer-lib:0.0.7' implementation 'com.scottyab:rootbeer-lib:0.0.8'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha03' androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha03'
androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test:rules:1.3.0-alpha03' androidTestImplementation 'androidx.test:rules:1.3.0-beta01'
androidTestImplementation 'com.google.code.findbugs:jsr305:3.0.2' androidTestImplementation 'com.google.code.findbugs:jsr305:3.0.2'
/* Dagger2 - We are going to use dagger.android which includes /* Dagger2 - We are going to use dagger.android which includes
* support for Activity and fragment injection so we need to include * support for Activity and fragment injection so we need to include
* the following dependencies */ * the following dependencies */
implementation 'com.google.dagger:dagger-android:2.25.2' implementation "com.google.dagger:dagger-android:$dagger_version"
implementation 'com.google.dagger:dagger-android-support:2.25.2' implementation "com.google.dagger:dagger-android-support:$dagger_version"
annotationProcessor 'com.google.dagger:dagger-compiler:2.25.2' annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
annotationProcessor 'com.google.dagger:dagger-android-processor:2.25.2' annotationProcessor "com.google.dagger:dagger-android-processor:$dagger_version"
kapt 'com.google.dagger:dagger-android-processor:2.25.2' kapt "com.google.dagger:dagger-android-processor:$dagger_version"
/* Dagger2 - default dependency */ /* Dagger2 - default dependency */
kapt 'com.google.dagger:dagger-compiler:2.25.2' kapt "com.google.dagger:dagger-compiler:$dagger_version"
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0' androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
} }

View file

@ -82,6 +82,7 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".plugins.pump.danaRS.activities.PairingHelperActivity" /> <activity android:name=".plugins.pump.danaRS.activities.PairingHelperActivity" />
<activity android:name=".plugins.general.maintenance.activities.PrefImportListActivity" />
<activity android:name=".historyBrowser.HistoryBrowseActivity" /> <activity android:name=".historyBrowser.HistoryBrowseActivity" />
<activity android:name=".activities.SurveyActivity" /> <activity android:name=".activities.SurveyActivity" />
<activity android:name=".activities.StatsActivity" /> <activity android:name=".activities.StatsActivity" />

View file

@ -47,7 +47,6 @@ import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionChec
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
import info.nightscout.androidaps.setupwizard.SetupWizardActivity import info.nightscout.androidaps.setupwizard.SetupWizardActivity
import info.nightscout.androidaps.utils.tabs.TabPageAdapter
import info.nightscout.androidaps.utils.AndroidPermission import info.nightscout.androidaps.utils.AndroidPermission
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.LocaleHelper import info.nightscout.androidaps.utils.LocaleHelper
@ -58,6 +57,8 @@ import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.IconsProvider import info.nightscout.androidaps.utils.resources.IconsProvider
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.tabs.TabPageAdapter
import info.nightscout.androidaps.utils.ui.UIRunnable
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
@ -160,12 +161,9 @@ class MainActivity : NoSplashAppCompatActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
protectionCheck.queryProtection(this, ProtectionCheck.Protection.APPLICATION, null, protectionCheck.queryProtection(this, ProtectionCheck.Protection.APPLICATION, null,
Runnable { UIRunnable(Runnable { OKDialog.show(this, "", resourceHelper.gs(R.string.authorizationfailed), Runnable { finish() }) }),
OKDialog.show(this, "", resourceHelper.gs(R.string.authorizationfailed), Runnable { finish() }) UIRunnable(Runnable { OKDialog.show(this, "", resourceHelper.gs(R.string.authorizationfailed), Runnable { finish() }) })
}, )
Runnable {
OKDialog.show(this, "", resourceHelper.gs(R.string.authorizationfailed), Runnable { finish() })
})
} }
private fun setWakeLock() { private fun setWakeLock() {
@ -197,6 +195,7 @@ class MainActivity : NoSplashAppCompatActivity() {
} }
} }
main_pager.adapter = pageAdapter main_pager.adapter = pageAdapter
main_pager.offscreenPageLimit = 8 // This may cause more memory consumption
checkPluginPreferences(main_pager) checkPluginPreferences(main_pager)
// Tabs // Tabs

View file

@ -280,7 +280,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
} }
for (plugin in pluginStore.plugins) { for (plugin in pluginStore.plugins) {
pref?.let { pref-> pref.getKey()?.let { plugin.updatePreferenceSummary(pref) }} pref?.let { it.key?.let { plugin.updatePreferenceSummary(pref) }}
} }
val hmacPasswords = arrayOf( val hmacPasswords = arrayOf(

View file

@ -106,7 +106,7 @@ public class CareportalEvent implements DataPointWithLabelInterface, Interval {
} }
public String age(boolean useShortText, ResourceHelper resourceHelper) { public String age(boolean useShortText, ResourceHelper resourceHelper) {
Map<TimeUnit, Long> diff = computeDiff(date, System.currentTimeMillis()); Map<TimeUnit, Long> diff = DateUtil.computeDiff(date, System.currentTimeMillis());
String days = " " + resourceHelper.gs(R.string.days) + " "; String days = " " + resourceHelper.gs(R.string.days) + " ";
String hours = " " + resourceHelper.gs(R.string.hours) + " "; String hours = " " + resourceHelper.gs(R.string.hours) + " ";
@ -135,23 +135,6 @@ public class CareportalEvent implements DataPointWithLabelInterface, Interval {
"}"; "}";
} }
//Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}
private static Map<TimeUnit, Long> computeDiff(long date1, long date2) {
long diffInMillies = date2 - date1;
List<TimeUnit> units = new ArrayList<>(EnumSet.allOf(TimeUnit.class));
Collections.reverse(units);
Map<TimeUnit, Long> result = new LinkedHashMap<>();
long milliesRest = diffInMillies;
for (TimeUnit unit : units) {
long diff = unit.convert(milliesRest, TimeUnit.MILLISECONDS);
long diffInMilliesForUnit = unit.toMillis(diff);
milliesRest = milliesRest - diffInMilliesForUnit;
result.put(unit, diff);
}
return result;
}
public boolean isEvent5minBack(List<CareportalEvent> list, long time) { public boolean isEvent5minBack(List<CareportalEvent> list, long time) {
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
CareportalEvent event = list.get(i); CareportalEvent event = list.get(i);

View file

@ -510,9 +510,9 @@ public class TemporaryBasal implements Interval, DbObjectBase {
} else { } else {
rate = absoluteRate; rate = absoluteRate;
} }
return DecimalFormatter.to2Decimal(rate) + "U/h "; return DecimalFormatter.to2Decimal(rate) + "U/h";
} else { // percent } else { // percent
return percentRate + "% "; return percentRate + "%";
} }
} }

View file

@ -6,6 +6,7 @@ import info.nightscout.androidaps.MainActivity
import info.nightscout.androidaps.activities.* import info.nightscout.androidaps.activities.*
import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity import info.nightscout.androidaps.historyBrowser.HistoryBrowseActivity
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity
import info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImportListActivity
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity
import info.nightscout.androidaps.plugins.general.smsCommunicator.activities.SmsCommunicatorOtpActivity 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.RileyLinkBLEScanActivity
@ -18,8 +19,6 @@ import info.nightscout.androidaps.plugins.pump.insight.activities.InsightAlertAc
import info.nightscout.androidaps.plugins.pump.insight.activities.InsightPairingActivity import info.nightscout.androidaps.plugins.pump.insight.activities.InsightPairingActivity
import info.nightscout.androidaps.plugins.pump.insight.activities.InsightPairingInformationActivity import info.nightscout.androidaps.plugins.pump.insight.activities.InsightPairingInformationActivity
import info.nightscout.androidaps.plugins.pump.medtronic.dialog.MedtronicHistoryActivity import info.nightscout.androidaps.plugins.pump.medtronic.dialog.MedtronicHistoryActivity
import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.PodHistoryActivity
import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.PodManagementActivity
import info.nightscout.androidaps.setupwizard.SetupWizardActivity import info.nightscout.androidaps.setupwizard.SetupWizardActivity
@Module @Module
@ -50,5 +49,5 @@ abstract class ActivitiesModule {
@ContributesAndroidInjector abstract fun contributesStatsActivity(): StatsActivity @ContributesAndroidInjector abstract fun contributesStatsActivity(): StatsActivity
@ContributesAndroidInjector abstract fun contributesSurveyActivity(): SurveyActivity @ContributesAndroidInjector abstract fun contributesSurveyActivity(): SurveyActivity
@ContributesAndroidInjector abstract fun contributesTDDStatsActivity(): TDDStatsActivity @ContributesAndroidInjector abstract fun contributesTDDStatsActivity(): TDDStatsActivity
@ContributesAndroidInjector abstract fun contributesPrefImportListActivity(): PrefImportListActivity
} }

View file

@ -69,7 +69,8 @@ import javax.inject.Singleton
PreferencesModule::class, PreferencesModule::class,
OverviewModule::class, OverviewModule::class,
DataClassesModule::class, DataClassesModule::class,
SMSModule::class SMSModule::class,
UIModule::class
] ]
) )
interface AppComponent : AndroidInjector<MainApp> { interface AppComponent : AndroidInjector<MainApp> {

View file

@ -23,7 +23,11 @@ import info.nightscout.androidaps.utils.storage.FileStorage
import info.nightscout.androidaps.utils.storage.Storage import info.nightscout.androidaps.utils.storage.Storage
import javax.inject.Singleton import javax.inject.Singleton
@Module(includes = [AppModule.AppBindings::class, PluginsModule::class]) @Module(includes = [
AppModule.AppBindings::class,
PluginsModule::class,
SkinsModule::class
])
open class AppModule { open class AppModule {
@Provides @Provides

View file

@ -4,6 +4,8 @@ import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState
import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.PodHistoryActivity
import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.PodManagementActivity
import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.pages.InitPodRefreshAction import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.pages.InitPodRefreshAction
import info.nightscout.androidaps.plugins.pump.omnipod.driver.comm.AapsOmnipodManager import info.nightscout.androidaps.plugins.pump.omnipod.driver.comm.AapsOmnipodManager
import info.nightscout.androidaps.plugins.pump.omnipod.driver.ui.OmnipodUITask import info.nightscout.androidaps.plugins.pump.omnipod.driver.ui.OmnipodUITask
@ -12,10 +14,15 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.ui.OmnipodUITask
@Suppress("unused") @Suppress("unused")
abstract class OmnipodModule { abstract class OmnipodModule {
// Activities
@ContributesAndroidInjector abstract fun contributesPodManagementActivity(): PodManagementActivity
@ContributesAndroidInjector abstract fun contributesPodHistoryActivity(): PodHistoryActivity
@ContributesAndroidInjector abstract fun omnipodCommunicationManagerProvider(): OmnipodCommunicationManager @ContributesAndroidInjector abstract fun omnipodCommunicationManagerProvider(): OmnipodCommunicationManager
@ContributesAndroidInjector abstract fun omnipodUITaskProvider(): OmnipodUITask @ContributesAndroidInjector abstract fun omnipodUITaskProvider(): OmnipodUITask
@ContributesAndroidInjector abstract fun aapsOmnipodManagerProvider(): AapsOmnipodManager @ContributesAndroidInjector abstract fun aapsOmnipodManagerProvider(): AapsOmnipodManager
@ContributesAndroidInjector abstract fun initPodRefreshAction(): InitPodRefreshAction @ContributesAndroidInjector abstract fun initPodRefreshAction(): InitPodRefreshAction
@ContributesAndroidInjector abstract fun podSessionState(): PodSessionState @ContributesAndroidInjector abstract fun podSessionState(): PodSessionState
}
}

View file

@ -3,6 +3,7 @@ package info.nightscout.androidaps.dependencyInjection
import dagger.Module import dagger.Module
import dagger.android.ContributesAndroidInjector import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs import info.nightscout.androidaps.plugins.general.maintenance.ImportExportPrefs
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
import info.nightscout.androidaps.plugins.general.maintenance.formats.ClassicPrefsFormat import info.nightscout.androidaps.plugins.general.maintenance.formats.ClassicPrefsFormat
import info.nightscout.androidaps.plugins.general.maintenance.formats.EncryptedPrefsFormat import info.nightscout.androidaps.plugins.general.maintenance.formats.EncryptedPrefsFormat
import info.nightscout.androidaps.utils.CryptoUtil import info.nightscout.androidaps.utils.CryptoUtil
@ -15,4 +16,5 @@ abstract class PreferencesModule {
@ContributesAndroidInjector abstract fun importExportPrefsInjector(): ImportExportPrefs @ContributesAndroidInjector abstract fun importExportPrefsInjector(): ImportExportPrefs
@ContributesAndroidInjector abstract fun encryptedPrefsFormatInjector(): EncryptedPrefsFormat @ContributesAndroidInjector abstract fun encryptedPrefsFormatInjector(): EncryptedPrefsFormat
@ContributesAndroidInjector abstract fun classicPrefsFormatInjector(): ClassicPrefsFormat @ContributesAndroidInjector abstract fun classicPrefsFormatInjector(): ClassicPrefsFormat
@ContributesAndroidInjector abstract fun prefImportListProviderInjector(): PrefFileListProvider
} }

View file

@ -0,0 +1,30 @@
package info.nightscout.androidaps.dependencyInjection
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.multibindings.IntKey
import dagger.multibindings.IntoMap
import info.nightscout.androidaps.skins.SkinButtonsOn
import info.nightscout.androidaps.skins.SkinClassic
import info.nightscout.androidaps.skins.SkinInterface
import javax.inject.Qualifier
@Module
open class SkinsModule {
@Provides
@Skin
@IntoMap
@IntKey(0)
fun bindsSkinClassic(skinClassic: SkinClassic): SkinInterface = skinClassic
@Provides
@Skin
@IntoMap
@IntKey(10)
fun bindsSkinButtonsOn(skinButtonsOn: SkinButtonsOn): SkinInterface = skinButtonsOn
@Qualifier
annotation class Skin
}

View file

@ -0,0 +1,21 @@
package info.nightscout.androidaps.dependencyInjection
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.plugins.aps.loop.APSResult
import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalResultAMA
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.*
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationWithAction
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Thread
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobThread
import info.nightscout.androidaps.skins.SkinListPreference
@Module
@Suppress("unused")
abstract class UIModule {
@ContributesAndroidInjector abstract fun skinListPreferenceInjector(): SkinListPreference
}

View file

@ -212,7 +212,7 @@ class ObjectivesFragment : DaggerFragment() {
bundle.putInt("currentTask", taskPosition) bundle.putInt("currentTask", taskPosition)
dialog.arguments = bundle dialog.arguments = bundle
ObjectivesExamDialog.objective = objective ObjectivesExamDialog.objective = objective
fragmentManager?.let { dialog.show(it, "ObjectivesFragment") } dialog.show(childFragmentManager, "ObjectivesFragment")
} }
} }
// horizontal line // horizontal line

View file

@ -41,7 +41,7 @@ class PhoneCheckerPlugin @Inject constructor(
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
phoneRooted = RootBeer(context).isRootedWithoutBusyBoxCheck() phoneRooted = RootBeer(context).isRooted()
devMode = isDevModeEnabled() devMode = isDevModeEnabled()
} }
} }

View file

@ -116,6 +116,14 @@ class VersionCheckerUtils @Inject constructor(
private fun String?.toNumberList() = private fun String?.toNumberList() =
this?.numericVersionPart().takeIf { !it.isNullOrBlank() }?.split(".")?.map { it.toInt() } this?.numericVersionPart().takeIf { !it.isNullOrBlank() }?.split(".")?.map { it.toInt() }
fun versionDigits(versionString: String?): IntArray {
val digits = mutableListOf<Int>()
versionString?.numericVersionPart().toNumberList()?.let {
digits.addAll(it.take(4))
}
return digits.toIntArray()
}
fun findVersion(file: String?): String? { fun findVersion(file: String?): String? {
val regex = "(.*)version(.*)\"(((\\d+)\\.)+(\\d+))\"(.*)".toRegex() val regex = "(.*)version(.*)\"(((\\d+)\\.)+(\\d+))\"(.*)".toRegex()
return file?.lines()?.filter { regex.matches(it) }?.mapNotNull { regex.matchEntire(it)?.groupValues?.getOrNull(3) }?.firstOrNull() return file?.lines()?.filter { regex.matches(it) }?.mapNotNull { regex.matchEntire(it)?.groupValues?.getOrNull(3) }?.firstOrNull()

View file

@ -25,14 +25,15 @@ import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction
import info.nightscout.androidaps.plugins.general.overview.StatusLightHandler import info.nightscout.androidaps.plugins.general.overview.StatusLightHandler
import info.nightscout.androidaps.queue.Callback import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.SingleClickButton import info.nightscout.androidaps.utils.SingleClickButton
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.extensions.plusAssign import info.nightscout.androidaps.utils.extensions.plusAssign
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.extensions.toVisibility import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.ui.UIRunnable
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.actions_fragment.* import kotlinx.android.synthetic.main.actions_fragment.*
@ -68,19 +69,19 @@ class ActionsFragment : DaggerFragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
actions_profileswitch.setOnClickListener { actions_profileswitch.setOnClickListener {
fragmentManager?.let { ProfileSwitchDialog().show(it, "Actions") } ProfileSwitchDialog().show(childFragmentManager, "Actions")
} }
actions_temptarget.setOnClickListener { actions_temptarget.setOnClickListener {
fragmentManager?.let { TempTargetDialog().show(it, "Actions") } TempTargetDialog().show(childFragmentManager, "Actions")
} }
actions_extendedbolus.setOnClickListener { actions_extendedbolus.setOnClickListener {
activity?.let { activity -> activity?.let { activity ->
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, Runnable { protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable(Runnable {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.extended_bolus), resourceHelper.gs(R.string.ebstopsloop), OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.extended_bolus), resourceHelper.gs(R.string.ebstopsloop),
Runnable { Runnable {
fragmentManager?.let { ExtendedBolusDialog().show(it, "Actions") } ExtendedBolusDialog().show(childFragmentManager, "Actions")
}, null) }, null)
}) }))
} }
} }
actions_extendedbolus_cancel.setOnClickListener { actions_extendedbolus_cancel.setOnClickListener {
@ -101,7 +102,7 @@ class ActionsFragment : DaggerFragment() {
} }
} }
actions_settempbasal.setOnClickListener { actions_settempbasal.setOnClickListener {
fragmentManager?.let { TempBasalDialog().show(it, "Actions") } TempBasalDialog().show(childFragmentManager, "Actions")
} }
actions_canceltempbasal.setOnClickListener { actions_canceltempbasal.setOnClickListener {
if (activePlugin.activeTreatments.isTempBasalInProgress) { if (activePlugin.activeTreatments.isTempBasalInProgress) {
@ -122,25 +123,25 @@ class ActionsFragment : DaggerFragment() {
} }
actions_fill.setOnClickListener { actions_fill.setOnClickListener {
activity?.let { activity -> activity?.let { activity ->
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, Runnable { fragmentManager?.let { FillDialog().show(it, "FillDialog") } }) protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable(Runnable { FillDialog().show(childFragmentManager, "FillDialog") }))
} }
} }
actions_historybrowser.setOnClickListener { startActivity(Intent(context, HistoryBrowseActivity::class.java)) } actions_historybrowser.setOnClickListener { startActivity(Intent(context, HistoryBrowseActivity::class.java)) }
actions_tddstats.setOnClickListener { startActivity(Intent(context, TDDStatsActivity::class.java)) } actions_tddstats.setOnClickListener { startActivity(Intent(context, TDDStatsActivity::class.java)) }
actions_bgcheck.setOnClickListener { actions_bgcheck.setOnClickListener {
fragmentManager?.let { CareDialog().setOptions(CareDialog.EventType.BGCHECK, R.string.careportal_bgcheck).show(it, "Actions") } CareDialog().setOptions(CareDialog.EventType.BGCHECK, R.string.careportal_bgcheck).show(childFragmentManager, "Actions")
} }
actions_cgmsensorinsert.setOnClickListener { actions_cgmsensorinsert.setOnClickListener {
fragmentManager?.let { CareDialog().setOptions(CareDialog.EventType.SENSOR_INSERT, R.string.careportal_cgmsensorinsert).show(it, "Actions") } CareDialog().setOptions(CareDialog.EventType.SENSOR_INSERT, R.string.careportal_cgmsensorinsert).show(childFragmentManager, "Actions")
} }
actions_pumpbatterychange.setOnClickListener { actions_pumpbatterychange.setOnClickListener {
fragmentManager?.let { CareDialog().setOptions(CareDialog.EventType.BATTERY_CHANGE, R.string.careportal_pumpbatterychange).show(it, "Actions") } CareDialog().setOptions(CareDialog.EventType.BATTERY_CHANGE, R.string.careportal_pumpbatterychange).show(childFragmentManager, "Actions")
} }
actions_note.setOnClickListener { actions_note.setOnClickListener {
fragmentManager?.let { CareDialog().setOptions(CareDialog.EventType.NOTE, R.string.careportal_note).show(it, "Actions") } CareDialog().setOptions(CareDialog.EventType.NOTE, R.string.careportal_note).show(childFragmentManager, "Actions")
} }
actions_exercise.setOnClickListener { actions_exercise.setOnClickListener {
fragmentManager?.let { CareDialog().setOptions(CareDialog.EventType.EXERCISE, R.string.careportal_exercise).show(it, "Actions") } CareDialog().setOptions(CareDialog.EventType.EXERCISE, R.string.careportal_exercise).show(childFragmentManager, "Actions")
} }
sp.putBoolean(R.string.key_objectiveuseactions, true) sp.putBoolean(R.string.key_objectiveuseactions, true)

View file

@ -72,7 +72,7 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
args.putString("event", AutomationEvent(mainApp).toJSON()) args.putString("event", AutomationEvent(mainApp).toJSON())
args.putInt("position", -1) // New event args.putInt("position", -1) // New event
dialog.arguments = args dialog.arguments = args
fragmentManager?.let { dialog.show(it, "EditEventDialog") } dialog.show(childFragmentManager, "EditEventDialog")
} }
val callback: ItemTouchHelper.Callback = SimpleItemTouchHelperCallback(eventListAdapter) val callback: ItemTouchHelper.Callback = SimpleItemTouchHelperCallback(eventListAdapter)
@ -182,7 +182,7 @@ class AutomationFragment : DaggerFragment(), OnStartDragListener {
args.putString("event", event.toJSON()) args.putString("event", event.toJSON())
args.putInt("position", position) args.putInt("position", position)
dialog.arguments = args dialog.arguments = args
fragmentManager?.let { dialog.show(it, "EditEventDialog") } dialog.show(childFragmentManager, "EditEventDialog")
} }
// Start a drag whenever the handle view it touched // Start a drag whenever the handle view it touched
holder.iconSort.setOnTouchListener { v: View, motionEvent: MotionEvent -> holder.iconSort.setOnTouchListener { v: View, motionEvent: MotionEvent ->

View file

@ -66,15 +66,15 @@ class EditEventDialog : DialogFragmentWithDate() {
args.putString("trigger", event.trigger.toJSON()) args.putString("trigger", event.trigger.toJSON())
val dialog = EditTriggerDialog() val dialog = EditTriggerDialog()
dialog.arguments = args dialog.arguments = args
fragmentManager?.let { dialog.show(it, "EditTriggerDialog") } dialog.show(childFragmentManager, "EditTriggerDialog")
} }
// setup action list view // setup action list view
fragmentManager?.let { actionListAdapter = ActionListAdapter() } actionListAdapter = ActionListAdapter()
automation_actionListView.layoutManager = LinearLayoutManager(context) automation_actionListView.layoutManager = LinearLayoutManager(context)
automation_actionListView.adapter = actionListAdapter automation_actionListView.adapter = actionListAdapter
automation_addAction.setOnClickListener { fragmentManager?.let { ChooseActionDialog().show(it, "ChooseActionDialog") } } automation_addAction.setOnClickListener { ChooseActionDialog().show(childFragmentManager, "ChooseActionDialog") }
showPreconditions() showPreconditions()
@ -187,9 +187,7 @@ class EditEventDialog : DialogFragmentWithDate() {
args.putString("action", action.toJSON()) args.putString("action", action.toJSON())
val dialog = EditActionDialog() val dialog = EditActionDialog()
dialog.arguments = args dialog.arguments = args
fragmentManager?.let { dialog.show(childFragmentManager, "EditActionDialog")
dialog.show(it, "EditActionDialog")
}
} }
} }
view.findViewById<ImageView>(R.id.automation_iconTrash).setOnClickListener { view.findViewById<ImageView>(R.id.automation_iconTrash).setOnClickListener {

View file

@ -125,9 +125,7 @@ class CareportalFragment : DaggerFragment(), View.OnClickListener {
R.id.careportal_openapsoffline -> newDialog.setOptions(OPENAPSOFFLINE, R.string.careportal_openapsoffline) R.id.careportal_openapsoffline -> newDialog.setOptions(OPENAPSOFFLINE, R.string.careportal_openapsoffline)
R.id.careportal_temporarytarget -> newDialog.setOptions(TEMPTARGET, R.string.careportal_temporarytarget) R.id.careportal_temporarytarget -> newDialog.setOptions(TEMPTARGET, R.string.careportal_temporarytarget)
} }
fragmentManager?.let { NewNSTreatmentDialog().show(childFragmentManager, "CareportalFragment")
NewNSTreatmentDialog().show(it, "CareportalFragment")
}
} }
private fun updateGUI() { private fun updateGUI() {

View file

@ -6,12 +6,12 @@ import android.bluetooth.BluetoothAdapter
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Build
import android.os.Environment
import android.provider.Settings import android.provider.Settings
import androidx.activity.invoke
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import info.nightscout.androidaps.BuildConfig import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.PreferencesActivity import info.nightscout.androidaps.activities.PreferencesActivity
@ -22,9 +22,9 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper
import info.nightscout.androidaps.plugins.general.maintenance.formats.* import info.nightscout.androidaps.plugins.general.maintenance.formats.*
import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword import info.nightscout.androidaps.plugins.general.smsCommunicator.otp.OneTimePassword
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.alertDialogs.OKDialog.show import info.nightscout.androidaps.utils.alertDialogs.OKDialog.show
import info.nightscout.androidaps.utils.ToastUtils
import info.nightscout.androidaps.utils.alertDialogs.PrefImportSummaryDialog import info.nightscout.androidaps.utils.alertDialogs.PrefImportSummaryDialog
import info.nightscout.androidaps.utils.alertDialogs.TwoMessagesAlertDialog import info.nightscout.androidaps.utils.alertDialogs.TwoMessagesAlertDialog
import info.nightscout.androidaps.utils.alertDialogs.WarningDialog import info.nightscout.androidaps.utils.alertDialogs.WarningDialog
@ -32,8 +32,6 @@ import info.nightscout.androidaps.utils.buildHelper.BuildHelper
import info.nightscout.androidaps.utils.protection.PasswordCheck import info.nightscout.androidaps.utils.protection.PasswordCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.joda.time.DateTime
import org.joda.time.Days
import java.io.File import java.io.File
import java.io.FileNotFoundException import java.io.FileNotFoundException
import java.io.IOException import java.io.IOException
@ -51,37 +49,25 @@ private val PERMISSIONS_STORAGE = arrayOf(
Manifest.permission.WRITE_EXTERNAL_STORAGE Manifest.permission.WRITE_EXTERNAL_STORAGE
) )
private const val IMPORT_AGE_NOT_YET_OLD_DAYS = 60
@Singleton @Singleton
class ImportExportPrefs @Inject constructor( class ImportExportPrefs @Inject constructor(
private var log: AAPSLogger, private var log: AAPSLogger,
private val resourceHelper: ResourceHelper, private val resourceHelper: ResourceHelper,
private val sp: SP, private val sp: SP,
private val buildHelper: BuildHelper, private val buildHelper: BuildHelper,
private val otp: OneTimePassword,
private val rxBus: RxBusWrapper, private val rxBus: RxBusWrapper,
private val passwordCheck: PasswordCheck, private val passwordCheck: PasswordCheck,
private val classicPrefsFormat: ClassicPrefsFormat, private val classicPrefsFormat: ClassicPrefsFormat,
private val encryptedPrefsFormat: EncryptedPrefsFormat private val encryptedPrefsFormat: EncryptedPrefsFormat,
private val prefFileList: PrefFileListProvider
) { ) {
val TAG = LTag.CORE val TAG = LTag.CORE
private val path = File(Environment.getExternalStorageDirectory().toString())
private val file = File(path, resourceHelper.gs(R.string.app_name) + "Preferences")
private val encFile = File(path, resourceHelper.gs(R.string.app_name) + "Preferences.json")
fun prefsImportFile(): File {
return if (encFile.exists()) encFile else file
}
fun prefsFileExists(): Boolean { fun prefsFileExists(): Boolean {
return encFile.exists() || file.exists() return prefFileList.listPreferenceFiles().size > 0
} }
fun exportSharedPreferences(f: Fragment) { fun exportSharedPreferences(f: Fragment) {
f.activity?.let { exportSharedPreferences(it) } f.activity?.let { exportSharedPreferences(it) }
} }
@ -135,9 +121,6 @@ class ImportExportPrefs @Inject constructor(
return name return name
} }
private fun getCurrentDeviceModelString() =
Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")"
private fun prefsEncryptionIsDisabled() = private fun prefsEncryptionIsDisabled() =
buildHelper.isEngineeringMode() && !sp.getBoolean(resourceHelper.gs(R.string.key_maintenance_encrypt_exported_prefs), true) buildHelper.isEngineeringMode() && !sp.getBoolean(resourceHelper.gs(R.string.key_maintenance_encrypt_exported_prefs), true)
@ -173,36 +156,41 @@ class ImportExportPrefs @Inject constructor(
return true return true
} }
private fun askToConfirmExport(activity: Activity, then: ((password: String) -> Unit)) { private fun askToConfirmExport(activity: Activity, fileToExport: File, then: ((password: String) -> Unit)) {
if (!prefsEncryptionIsDisabled() && !assureMasterPasswordSet(activity, R.string.nav_export)) return if (!prefsEncryptionIsDisabled() && !assureMasterPasswordSet(activity, R.string.nav_export)) return
TwoMessagesAlertDialog.showAlert(activity, resourceHelper.gs(R.string.nav_export), TwoMessagesAlertDialog.showAlert(activity, resourceHelper.gs(R.string.nav_export),
resourceHelper.gs(R.string.export_to) + " " + encFile + " ?", resourceHelper.gs(R.string.export_to) + " " + fileToExport + " ?",
resourceHelper.gs(R.string.password_preferences_encrypt_prompt), { resourceHelper.gs(R.string.password_preferences_encrypt_prompt), {
askForMasterPassIfNeeded(activity, R.string.preferences_export_canceled, then) askForMasterPassIfNeeded(activity, R.string.preferences_export_canceled, then)
}, null, R.drawable.ic_header_export) }, null, R.drawable.ic_header_export)
} }
private fun askToConfirmImport(activity: Activity, fileToImport: File, then: ((password: String) -> Unit)) { private fun askToConfirmImport(activity: Activity, fileToImport: PrefsFile, then: ((password: String) -> Unit)) {
if (encFile.exists()) { if (fileToImport.handler == PrefsFormatsHandler.ENCRYPTED) {
if (!assureMasterPasswordSet(activity, R.string.nav_import)) return if (!assureMasterPasswordSet(activity, R.string.nav_import)) return
TwoMessagesAlertDialog.showAlert(activity, resourceHelper.gs(R.string.nav_import), TwoMessagesAlertDialog.showAlert(activity, resourceHelper.gs(R.string.nav_import),
resourceHelper.gs(R.string.import_from) + " " + fileToImport + " ?", resourceHelper.gs(R.string.import_from) + " " + fileToImport.file + " ?",
resourceHelper.gs(R.string.password_preferences_decrypt_prompt), { resourceHelper.gs(R.string.password_preferences_decrypt_prompt), {
askForMasterPass(activity, R.string.preferences_import_canceled, then) askForMasterPass(activity, R.string.preferences_import_canceled, then)
}, null, R.drawable.ic_header_import) }, null, R.drawable.ic_header_import)
} else { } else {
OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.nav_import), OKDialog.showConfirmation(activity, resourceHelper.gs(R.string.nav_import),
resourceHelper.gs(R.string.import_from) + " " + fileToImport + " ?", resourceHelper.gs(R.string.import_from) + " " + fileToImport.file + " ?",
Runnable { then("") }) Runnable { then("") })
} }
} }
private fun exportSharedPreferences(activity: Activity) { private fun exportSharedPreferences(activity: Activity) {
askToConfirmExport(activity) { password ->
prefFileList.ensureExportDirExists()
val legacyFile = prefFileList.legacyFile()
val newFile = prefFileList.newExportFile()
askToConfirmExport(activity, newFile) { password ->
try { try {
val entries: MutableMap<String, String> = mutableMapOf() val entries: MutableMap<String, String> = mutableMapOf()
for ((key, value) in sp.getAll()) { for ((key, value) in sp.getAll()) {
@ -211,12 +199,14 @@ class ImportExportPrefs @Inject constructor(
val prefs = Prefs(entries, prepareMetadata(activity)) val prefs = Prefs(entries, prepareMetadata(activity))
classicPrefsFormat.savePreferences(file, prefs) if (BuildConfig.DEBUG && buildHelper.isEngineeringMode()) {
encryptedPrefsFormat.savePreferences(encFile, prefs, password) classicPrefsFormat.savePreferences(legacyFile, prefs)
}
encryptedPrefsFormat.savePreferences(newFile, prefs, password)
ToastUtils.okToast(activity, resourceHelper.gs(R.string.exported)) ToastUtils.okToast(activity, resourceHelper.gs(R.string.exported))
} catch (e: FileNotFoundException) { } catch (e: FileNotFoundException) {
ToastUtils.errorToast(activity, resourceHelper.gs(R.string.filenotfound) + " " + encFile) ToastUtils.errorToast(activity, resourceHelper.gs(R.string.filenotfound) + " " + newFile)
log.error(TAG, "Unhandled exception", e) log.error(TAG, "Unhandled exception", e)
} catch (e: IOException) { } catch (e: IOException) {
ToastUtils.errorToast(activity, e.message) ToastUtils.errorToast(activity, e.message)
@ -226,21 +216,38 @@ class ImportExportPrefs @Inject constructor(
} }
fun importSharedPreferences(fragment: Fragment) { fun importSharedPreferences(fragment: Fragment) {
fragment.activity?.let { importSharedPreferences(it) } fragment.activity?.let { fragmentAct ->
val callForPrefFile = fragmentAct.registerForActivityResult(PrefsFileContract()) {
it?.let {
importSharedPreferences(fragmentAct, it)
}
}
callForPrefFile.invoke()
}
} }
fun importSharedPreferences(activity: Activity) { fun importSharedPreferences(activity: FragmentActivity) {
val callForPrefFile = activity.registerForActivityResult(PrefsFileContract()) {
it?.let {
importSharedPreferences(activity, it)
}
}
callForPrefFile.invoke()
}
val importFile = prefsImportFile() private fun importSharedPreferences(activity: Activity, importFile: PrefsFile) {
askToConfirmImport(activity, importFile) { password -> askToConfirmImport(activity, importFile) { password ->
val format: PrefsFormat = if (encFile.exists()) encryptedPrefsFormat else classicPrefsFormat val format: PrefsFormat = when (importFile.handler) {
PrefsFormatsHandler.CLASSIC -> classicPrefsFormat
PrefsFormatsHandler.ENCRYPTED -> encryptedPrefsFormat
}
try { try {
val prefs = format.loadPreferences(importFile, password) val prefs = format.loadPreferences(importFile.file, password)
prefs.metadata = checkMetadata(prefs.metadata) prefs.metadata = prefFileList.checkMetadata(prefs.metadata)
// import is OK when we do not have errors (warnings are allowed) // import is OK when we do not have errors (warnings are allowed)
val importOk = checkIfImportIsOk(prefs) val importOk = checkIfImportIsOk(prefs)
@ -276,45 +283,6 @@ class ImportExportPrefs @Inject constructor(
} }
} }
// check metadata for known issues, change their status and add info with explanations
private fun checkMetadata(metadata: Map<PrefsMetadataKey, PrefMetadata>): Map<PrefsMetadataKey, PrefMetadata> {
val meta = metadata.toMutableMap()
meta[PrefsMetadataKey.AAPS_FLAVOUR]?.let { flavour ->
val flavourOfPrefs = flavour.value
if (flavour.value != BuildConfig.FLAVOR) {
flavour.status = PrefsStatus.WARN
flavour.info = resourceHelper.gs(R.string.metadata_warning_different_flavour, flavourOfPrefs, BuildConfig.FLAVOR)
}
}
meta[PrefsMetadataKey.DEVICE_MODEL]?.let { model ->
if (model.value != getCurrentDeviceModelString()) {
model.status = PrefsStatus.WARN
model.info = resourceHelper.gs(R.string.metadata_warning_different_device)
}
}
meta[PrefsMetadataKey.CREATED_AT]?.let { createdAt ->
try {
val date1 = DateTime.parse(createdAt.value);
val date2 = DateTime.now()
val daysOld = Days.daysBetween(date1.toLocalDate(), date2.toLocalDate()).getDays()
if (daysOld > IMPORT_AGE_NOT_YET_OLD_DAYS) {
createdAt.status = PrefsStatus.WARN
createdAt.info = resourceHelper.gs(R.string.metadata_warning_old_export, daysOld.toString())
}
} catch (e: Exception) {
createdAt.status = PrefsStatus.WARN
createdAt.info = resourceHelper.gs(R.string.metadata_warning_date_format)
}
}
return meta
}
private fun checkIfImportIsOk(prefs: Prefs): Boolean { private fun checkIfImportIsOk(prefs: Prefs): Boolean {
var importOk = true var importOk = true

View file

@ -0,0 +1,219 @@
package info.nightscout.androidaps.plugins.general.maintenance
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Environment
import android.os.Parcelable
import androidx.activity.result.contract.ActivityResultContract
import info.nightscout.androidaps.BuildConfig
import info.nightscout.androidaps.R
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
import info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImportListActivity
import info.nightscout.androidaps.plugins.general.maintenance.formats.*
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.storage.Storage
import kotlinx.android.parcel.Parcelize
import kotlinx.android.parcel.RawValue
import org.joda.time.DateTime
import org.joda.time.Days
import org.joda.time.Hours
import org.joda.time.LocalDateTime
import org.joda.time.format.DateTimeFormat
import java.io.File
import javax.inject.Inject
import javax.inject.Singleton
enum class PrefsImportDir {
ROOT_DIR,
AAPS_DIR
}
@Parcelize
data class PrefsFile(
val file: File,
val baseDir: File,
val dirKind: PrefsImportDir,
val handler: PrefsFormatsHandler,
// metadata here is used only for list display
val metadata: @RawValue Map<PrefsMetadataKey, PrefMetadata>
) : Parcelable
class PrefsFileContract : ActivityResultContract<Void, PrefsFile>() {
companion object {
const val OUTPUT_PARAM = "prefs_file"
}
override fun parseResult(resultCode: Int, intent: Intent?): PrefsFile? {
return when (resultCode) {
Activity.RESULT_OK -> intent?.getParcelableExtra(OUTPUT_PARAM)
else -> null
}
}
override fun createIntent(context: Context, input: Void?): Intent {
return Intent(context, PrefImportListActivity::class.java)
}
}
fun getCurrentDeviceModelString() =
Build.MANUFACTURER + " " + Build.MODEL + " (" + Build.DEVICE + ")"
@Singleton
class PrefFileListProvider @Inject constructor(
private val resourceHelper: ResourceHelper,
private val classicPrefsFormat: ClassicPrefsFormat,
private val encryptedPrefsFormat: EncryptedPrefsFormat,
private val storage: Storage,
private val versionCheckerUtils: VersionCheckerUtils
) {
companion object {
private val path = File(Environment.getExternalStorageDirectory().toString())
private val aapsPath = File(path, "AAPS" + File.separator + "preferences")
private const val IMPORT_AGE_NOT_YET_OLD_DAYS = 60
}
/**
* This function tries to list possible preference files from main SDCard root dir and AAPS/preferences dir
* and tries to do quick assessment for preferences format plausibility.
* It does NOT load full metadata or is 100% accurate - it tries to do QUICK detection, based on:
* - file name and extension
* - predicted file contents
*/
fun listPreferenceFiles(loadMetadata: Boolean = false): MutableList<PrefsFile> {
val prefFiles = mutableListOf<PrefsFile>()
// searching rood dir for legacy files
path.walk().maxDepth(1).filter { it.isFile && (it.name.endsWith(".json") || it.name.contains("Preferences")) }.forEach {
val contents = storage.getFileContents(it)
val detectedNew = encryptedPrefsFormat.isPreferencesFile(it, contents)
val detectedOld = !detectedNew && classicPrefsFormat.isPreferencesFile(it, contents)
if (detectedNew || detectedOld) {
val formatHandler = if (detectedNew) PrefsFormatsHandler.ENCRYPTED else PrefsFormatsHandler.CLASSIC
prefFiles.add(PrefsFile(it, path, PrefsImportDir.ROOT_DIR, formatHandler, metadataFor(loadMetadata, formatHandler, contents)))
}
}
// searching dedicated dir, only for new JSON format
aapsPath.walk().filter { it.isFile && it.name.endsWith(".json") }.forEach {
val contents = storage.getFileContents(it)
if (encryptedPrefsFormat.isPreferencesFile(it, contents)) {
prefFiles.add(PrefsFile(it, aapsPath, PrefsImportDir.AAPS_DIR, PrefsFormatsHandler.ENCRYPTED, metadataFor(loadMetadata, PrefsFormatsHandler.ENCRYPTED, contents)))
}
}
// we sort only if we have metadata to be used for that
if (loadMetadata) {
prefFiles.sortWith(
compareByDescending<PrefsFile> { it.handler }
.thenBy { it.metadata[PrefsMetadataKey.AAPS_FLAVOUR]?.status }
.thenByDescending { it.metadata[PrefsMetadataKey.CREATED_AT]?.value }
)
}
return prefFiles
}
private fun metadataFor(loadMetadata: Boolean, formatHandler: PrefsFormatsHandler, contents: String): PrefMetadataMap {
if (!loadMetadata) {
return mapOf()
}
return checkMetadata(when (formatHandler) {
PrefsFormatsHandler.CLASSIC -> classicPrefsFormat.loadMetadata(contents)
PrefsFormatsHandler.ENCRYPTED -> encryptedPrefsFormat.loadMetadata(contents)
})
}
fun legacyFile(): File {
return File(path, resourceHelper.gs(R.string.app_name) + "Preferences")
}
fun ensureExportDirExists() {
if (!aapsPath.exists()) {
aapsPath.mkdirs()
}
}
fun newExportFile(): File {
val timeLocal = LocalDateTime.now().toString(DateTimeFormat.forPattern("yyyy-MM-dd'_'HHmmss"))
return File(aapsPath, timeLocal + "_" + BuildConfig.FLAVOR + ".json")
}
// check metadata for known issues, change their status and add info with explanations
fun checkMetadata(metadata: Map<PrefsMetadataKey, PrefMetadata>): Map<PrefsMetadataKey, PrefMetadata> {
val meta = metadata.toMutableMap()
meta[PrefsMetadataKey.AAPS_FLAVOUR]?.let { flavour ->
val flavourOfPrefs = flavour.value
if (flavour.value != BuildConfig.FLAVOR) {
flavour.status = PrefsStatus.WARN
flavour.info = resourceHelper.gs(R.string.metadata_warning_different_flavour, flavourOfPrefs, BuildConfig.FLAVOR)
}
}
meta[PrefsMetadataKey.DEVICE_MODEL]?.let { model ->
if (model.value != getCurrentDeviceModelString()) {
model.status = PrefsStatus.WARN
model.info = resourceHelper.gs(R.string.metadata_warning_different_device)
}
}
meta[PrefsMetadataKey.CREATED_AT]?.let { createdAt ->
try {
val date1 = DateTime.parse(createdAt.value);
val date2 = DateTime.now()
val daysOld = Days.daysBetween(date1.toLocalDate(), date2.toLocalDate()).getDays()
if (daysOld > IMPORT_AGE_NOT_YET_OLD_DAYS) {
createdAt.status = PrefsStatus.WARN
createdAt.info = resourceHelper.gs(R.string.metadata_warning_old_export, daysOld.toString())
}
} catch (e: Exception) {
createdAt.status = PrefsStatus.WARN
createdAt.info = resourceHelper.gs(R.string.metadata_warning_date_format)
}
}
meta[PrefsMetadataKey.AAPS_VERSION]?.let { version ->
val currentAppVer = versionCheckerUtils.versionDigits(BuildConfig.VERSION_NAME)
val metadataVer = versionCheckerUtils.versionDigits(version.value)
if ((currentAppVer.size >= 2) && (metadataVer.size >= 2) && (Math.abs(currentAppVer[1] - metadataVer[1]) > 1)) {
version.status = PrefsStatus.WARN
version.info = resourceHelper.gs(R.string.metadata_warning_different_version)
}
if ((currentAppVer.isNotEmpty()) && (metadataVer.isNotEmpty()) && (currentAppVer[0] != metadataVer[0])) {
version.status = PrefsStatus.WARN
version.info = resourceHelper.gs(R.string.metadata_urgent_different_version)
}
}
return meta
}
fun formatExportedAgo(utcTime: String): String {
val refTime = DateTime.now()
val itTime = DateTime.parse(utcTime)
val days = Days.daysBetween(itTime, refTime).days
val hours = Hours.hoursBetween(itTime, refTime).hours
return if (hours == 0) {
resourceHelper.gs(R.string.exported_less_than_hour_ago)
} else if ((hours < 24) && (hours > 0)) {
resourceHelper.gs(R.string.exported_ago, resourceHelper.gq(R.plurals.objective_hours, hours, hours))
} else if ((days < IMPORT_AGE_NOT_YET_OLD_DAYS) && (days > 0)) {
resourceHelper.gs(R.string.exported_ago, resourceHelper.gq(R.plurals.objective_days, days, days))
} else {
resourceHelper.gs(R.string.exported_at, utcTime.substring(0, 10))
}
}
}

View file

@ -0,0 +1,135 @@
package info.nightscout.androidaps.plugins.general.maintenance.activities
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import dagger.android.support.DaggerAppCompatActivity
import info.nightscout.androidaps.R
import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFile
import info.nightscout.androidaps.plugins.general.maintenance.PrefsFileContract
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsFormatsHandler
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsMetadataKey
import info.nightscout.androidaps.plugins.general.maintenance.formats.PrefsStatus
import info.nightscout.androidaps.utils.LocaleHelper
import info.nightscout.androidaps.utils.resources.ResourceHelper
import kotlinx.android.synthetic.main.maintenance_importlist_activity.*
import javax.inject.Inject
class PrefImportListActivity : DaggerAppCompatActivity() {
@Inject lateinit var resourceHelper: ResourceHelper
@Inject lateinit var prefFileListProvider: PrefFileListProvider
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setTheme(R.style.AppTheme)
setContentView(R.layout.maintenance_importlist_activity)
title = resourceHelper.gs(R.string.preferences_import_list_title)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
supportActionBar?.setDisplayShowTitleEnabled(true)
importlist_recyclerview.layoutManager = LinearLayoutManager(this)
importlist_recyclerview.adapter = RecyclerViewAdapter(prefFileListProvider.listPreferenceFiles(loadMetadata = true))
}
inner class RecyclerViewAdapter internal constructor(private var prefFileList: List<PrefsFile>) : RecyclerView.Adapter<RecyclerViewAdapter.PrefFileViewHolder>() {
inner class PrefFileViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
var fileName: TextView = itemView.findViewById(R.id.filelist_name)
var fileDir: TextView = itemView.findViewById(R.id.filelist_dir)
var metaDateTime: TextView = itemView.findViewById(R.id.meta_date_time)
var metaDeviceName: TextView = itemView.findViewById(R.id.meta_device_name)
var metaAppVersion: TextView = itemView.findViewById(R.id.meta_app_version)
var metaVariantFormat: TextView = itemView.findViewById(R.id.meta_variant_format)
var metalineName: View = itemView.findViewById(R.id.metaline_name)
var metaDateTimeIcon: View = itemView.findViewById(R.id.meta_date_time_icon)
init {
itemView.isClickable = true
itemView.setOnClickListener {
val prefFile = fileName.tag as PrefsFile
val i = Intent()
i.putExtra(PrefsFileContract.OUTPUT_PARAM, prefFile)
setResult(Activity.RESULT_OK, i)
finish()
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PrefFileViewHolder {
val v = LayoutInflater.from(parent.context).inflate(R.layout.maintenance_importlist_item, parent, false)
return PrefFileViewHolder(v)
}
override fun getItemCount(): Int {
return prefFileList.size
}
override fun onBindViewHolder(holder: PrefFileViewHolder, position: Int) {
val prefFile = prefFileList[position]
holder.fileName.text = prefFile.file.name
holder.fileName.tag = prefFile
holder.fileDir.text = resourceHelper.gs(R.string.in_directory, prefFile.file.parentFile.absolutePath)
val visible = if (prefFile.handler == PrefsFormatsHandler.CLASSIC) View.GONE else View.VISIBLE
holder.metalineName.visibility = visible
holder.metaDateTimeIcon.visibility = visible
holder.metaAppVersion.visibility = visible
if (prefFile.handler == PrefsFormatsHandler.CLASSIC) {
holder.metaVariantFormat.text = resourceHelper.gs(R.string.metadata_format_old)
holder.metaVariantFormat.setTextColor(resourceHelper.gc(R.color.metadataTextWarning))
holder.metaDateTime.text = " "
} else {
prefFile.metadata[PrefsMetadataKey.AAPS_FLAVOUR]?.let {
holder.metaVariantFormat.text = it.value
val color = if (it.status == PrefsStatus.OK) R.color.metadataOk else R.color.metadataTextWarning
holder.metaVariantFormat.setTextColor(resourceHelper.gc(color))
}
prefFile.metadata[PrefsMetadataKey.CREATED_AT]?.let {
holder.metaDateTime.text = prefFileListProvider.formatExportedAgo(it.value)
}
prefFile.metadata[PrefsMetadataKey.AAPS_VERSION]?.let {
holder.metaAppVersion.text = it.value
val color = if (it.status == PrefsStatus.OK) R.color.metadataOk else R.color.metadataTextWarning
holder.metaAppVersion.setTextColor(resourceHelper.gc(color))
}
prefFile.metadata[PrefsMetadataKey.DEVICE_NAME]?.let {
holder.metaDeviceName.text = it.value
}
}
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
finish()
return true
}
return false
}
public override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LocaleHelper.wrap(newBase))
}
}

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.general.maintenance.formats package info.nightscout.androidaps.plugins.general.maintenance.formats
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.storage.Storage import info.nightscout.androidaps.utils.storage.Storage
@ -19,6 +20,11 @@ class ClassicPrefsFormat @Inject constructor(
val FORMAT_KEY = "aaps_old" val FORMAT_KEY = "aaps_old"
} }
override fun isPreferencesFile(file: File, preloadedContents: String?): Boolean {
val contents = preloadedContents ?: storage.getFileContents(file)
return contents.contains("units::" + Constants.MGDL) || contents.contains("units::" + Constants.MMOL)
}
override fun savePreferences(file: File, prefs: Prefs, masterPassword: String?) { override fun savePreferences(file: File, prefs: Prefs, masterPassword: String?) {
try { try {
val contents = prefs.values.entries.joinToString("\n") { entry -> val contents = prefs.values.entries.joinToString("\n") { entry ->
@ -35,7 +41,6 @@ class ClassicPrefsFormat @Inject constructor(
override fun loadPreferences(file: File, masterPassword: String?): Prefs { override fun loadPreferences(file: File, masterPassword: String?): Prefs {
var lineParts: Array<String> var lineParts: Array<String>
val entries: MutableMap<String, String> = mutableMapOf() val entries: MutableMap<String, String> = mutableMapOf()
val metadata: MutableMap<PrefsMetadataKey, PrefMetadata> = mutableMapOf()
try { try {
val rawLines = storage.getFileContents(file).split("\n") val rawLines = storage.getFileContents(file).split("\n")
@ -46,9 +51,7 @@ class ClassicPrefsFormat @Inject constructor(
} }
} }
metadata[PrefsMetadataKey.FILE_FORMAT] = PrefMetadata(FORMAT_KEY, PrefsStatus.WARN, resourceHelper.gs(R.string.metadata_warning_outdated_format)) return Prefs(entries, loadMetadata())
return Prefs(entries, metadata)
} catch (e: FileNotFoundException) { } catch (e: FileNotFoundException) {
throw PrefFileNotFoundError(file.absolutePath) throw PrefFileNotFoundError(file.absolutePath)
@ -57,4 +60,10 @@ class ClassicPrefsFormat @Inject constructor(
} }
} }
override fun loadMetadata(contents: String?): PrefMetadataMap {
val metadata: MutableMap<PrefsMetadataKey, PrefMetadata> = mutableMapOf()
metadata[PrefsMetadataKey.FILE_FORMAT] = PrefMetadata(FORMAT_KEY, PrefsStatus.WARN, resourceHelper.gs(R.string.metadata_warning_outdated_format))
return metadata
}
} }

View file

@ -27,6 +27,16 @@ class EncryptedPrefsFormat @Inject constructor(
val FORMAT_KEY_NOENC = "aaps_structured" val FORMAT_KEY_NOENC = "aaps_structured"
private val KEY_CONSCIENCE = "if you remove/change this, please make sure you know the consequences!" private val KEY_CONSCIENCE = "if you remove/change this, please make sure you know the consequences!"
private val FORMAT_TEST_REGEX = Regex("(\\\"format\\\"\\s*\\:\\s*\\\"aaps_[^\"]*\\\")")
}
override fun isPreferencesFile(file: File, preloadedContents: String?): Boolean {
return if (file.absolutePath.endsWith(".json")) {
val contents = preloadedContents ?: storage.getFileContents(file)
FORMAT_TEST_REGEX.containsMatchIn(contents)
} else {
false
}
} }
override fun savePreferences(file: File, prefs: Prefs, masterPassword: String?) { override fun savePreferences(file: File, prefs: Prefs, masterPassword: String?) {
@ -97,7 +107,6 @@ class EncryptedPrefsFormat @Inject constructor(
override fun loadPreferences(file: File, masterPassword: String?): Prefs { override fun loadPreferences(file: File, masterPassword: String?): Prefs {
val entries: MutableMap<String, String> = mutableMapOf() val entries: MutableMap<String, String> = mutableMapOf()
val metadata: MutableMap<PrefsMetadataKey, PrefMetadata> = mutableMapOf()
val issues = LinkedList<String>() val issues = LinkedList<String>()
try { try {
@ -105,25 +114,11 @@ class EncryptedPrefsFormat @Inject constructor(
val fileContents = jsonBody.replace(Regex("(?is)(\\\"file_hash\\\"\\s*\\:\\s*\\\")([^\"]*)(\\\")"), "$1--to-be-calculated--$3") val fileContents = jsonBody.replace(Regex("(?is)(\\\"file_hash\\\"\\s*\\:\\s*\\\")([^\"]*)(\\\")"), "$1--to-be-calculated--$3")
val calculatedFileHash = cryptoUtil.hmac256(fileContents, KEY_CONSCIENCE) val calculatedFileHash = cryptoUtil.hmac256(fileContents, KEY_CONSCIENCE)
val container = JSONObject(jsonBody) val container = JSONObject(jsonBody)
val metadata: MutableMap<PrefsMetadataKey, PrefMetadata> = loadMetadata(container)
if (container.has(PrefsMetadataKey.FILE_FORMAT.key) && container.has("security") && container.has("content") && container.has("metadata")) { if (container.has(PrefsMetadataKey.FILE_FORMAT.key) && container.has("security") && container.has("content")) {
val fileFormat = container.getString(PrefsMetadataKey.FILE_FORMAT.key) val fileFormat = container.getString(PrefsMetadataKey.FILE_FORMAT.key)
if ((fileFormat != FORMAT_KEY_ENC) && (fileFormat != FORMAT_KEY_NOENC)) {
throw PrefFormatError("Unsupported file format: " + fileFormat)
}
val meta = container.getJSONObject("metadata")
val security = container.getJSONObject("security") val security = container.getJSONObject("security")
metadata[PrefsMetadataKey.FILE_FORMAT] = PrefMetadata(fileFormat, PrefsStatus.OK)
for (key in meta.keys()) {
val metaKey = PrefsMetadataKey.fromKey(key)
if (metaKey != null) {
metadata[metaKey] = PrefMetadata(meta.getString(key), PrefsStatus.OK)
}
}
val encrypted = fileFormat == FORMAT_KEY_ENC val encrypted = fileFormat == FORMAT_KEY_ENC
var secure: PrefsStatus = PrefsStatus.OK var secure: PrefsStatus = PrefsStatus.OK
var decryptedOk = false var decryptedOk = false
@ -208,8 +203,6 @@ class EncryptedPrefsFormat @Inject constructor(
} }
metadata[PrefsMetadataKey.ENCRYPTION] = PrefMetadata(encryptionDescStr, secure, issuesStr) metadata[PrefsMetadataKey.ENCRYPTION] = PrefMetadata(encryptionDescStr, secure, issuesStr)
} else {
metadata[PrefsMetadataKey.FILE_FORMAT] = PrefMetadata(resourceHelper.gs(R.string.prefdecrypt_wrong_json), PrefsStatus.ERROR)
} }
return Prefs(entries, metadata) return Prefs(entries, metadata)
@ -223,4 +216,35 @@ class EncryptedPrefsFormat @Inject constructor(
} }
} }
override fun loadMetadata(contents: String?): PrefMetadataMap {
contents?.let {
val container = JSONObject(contents)
return loadMetadata(container)
}
return mutableMapOf()
}
private fun loadMetadata(container: JSONObject): MutableMap<PrefsMetadataKey, PrefMetadata> {
val metadata: MutableMap<PrefsMetadataKey, PrefMetadata> = mutableMapOf()
if (container.has(PrefsMetadataKey.FILE_FORMAT.key) && container.has("security") && container.has("content") && container.has("metadata")) {
val fileFormat = container.getString(PrefsMetadataKey.FILE_FORMAT.key)
if ((fileFormat != FORMAT_KEY_ENC) && (fileFormat != FORMAT_KEY_NOENC)) {
metadata[PrefsMetadataKey.FILE_FORMAT] = PrefMetadata(resourceHelper.gs(R.string.metadata_format_other), PrefsStatus.ERROR)
} else {
val meta = container.getJSONObject("metadata")
metadata[PrefsMetadataKey.FILE_FORMAT] = PrefMetadata(fileFormat, PrefsStatus.OK)
for (key in meta.keys()) {
val metaKey = PrefsMetadataKey.fromKey(key)
if (metaKey != null) {
metadata[metaKey] = PrefMetadata(meta.getString(key), PrefsStatus.OK)
}
}
}
} else {
metadata[PrefsMetadataKey.FILE_FORMAT] = PrefMetadata(resourceHelper.gs(R.string.prefdecrypt_wrong_json), PrefsStatus.ERROR)
}
return metadata;
}
} }

View file

@ -1,12 +1,14 @@
package info.nightscout.androidaps.plugins.general.maintenance.formats package info.nightscout.androidaps.plugins.general.maintenance.formats
import android.content.Context import android.content.Context
import android.os.Parcelable
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import info.nightscout.androidaps.R import info.nightscout.androidaps.R
import kotlinx.android.parcel.Parcelize
import java.io.File import java.io.File
enum class PrefsMetadataKey(val key: String, @DrawableRes val icon:Int, @StringRes val label:Int) { enum class PrefsMetadataKey(val key: String, @DrawableRes val icon: Int, @StringRes val label: Int) {
FILE_FORMAT("format", R.drawable.ic_meta_format, R.string.metadata_label_format), FILE_FORMAT("format", R.drawable.ic_meta_format, R.string.metadata_label_format),
CREATED_AT("created_at", R.drawable.ic_meta_date, R.string.metadata_label_created_at), CREATED_AT("created_at", R.drawable.ic_meta_date, R.string.metadata_label_created_at),
@ -33,16 +35,15 @@ enum class PrefsMetadataKey(val key: String, @DrawableRes val icon:Int, @StringR
} }
} }
} }
fun formatForDisplay(context: Context, value:String): String { fun formatForDisplay(context: Context, value: String): String {
return when (this) { return when (this) {
FILE_FORMAT -> when (value) { FILE_FORMAT -> when (value) {
ClassicPrefsFormat.FORMAT_KEY -> context.getString(R.string.metadata_format_old) ClassicPrefsFormat.FORMAT_KEY -> context.getString(R.string.metadata_format_old)
EncryptedPrefsFormat.FORMAT_KEY_ENC -> context.getString(R.string.metadata_format_new) EncryptedPrefsFormat.FORMAT_KEY_ENC -> context.getString(R.string.metadata_format_new)
EncryptedPrefsFormat.FORMAT_KEY_NOENC -> context.getString(R.string.metadata_format_debug) EncryptedPrefsFormat.FORMAT_KEY_NOENC -> context.getString(R.string.metadata_format_debug)
else -> context.getString(R.string.metadata_format_other) else -> context.getString(R.string.metadata_format_other)
} }
CREATED_AT -> value.replace("T", " ").replace("Z", " (UTC)") CREATED_AT -> value.replace("T", " ").replace("Z", " (UTC)")
else -> value else -> value
@ -51,16 +52,21 @@ enum class PrefsMetadataKey(val key: String, @DrawableRes val icon:Int, @StringR
} }
data class PrefMetadata(var value : String, var status : PrefsStatus, var info : String? = null) @Parcelize
data class PrefMetadata(var value: String, var status: PrefsStatus, var info: String? = null) : Parcelable
data class Prefs(val values : Map<String, String>, var metadata : Map<PrefsMetadataKey, PrefMetadata>) typealias PrefMetadataMap = Map<PrefsMetadataKey, PrefMetadata>
data class Prefs(val values: Map<String, String>, var metadata: PrefMetadataMap)
interface PrefsFormat { interface PrefsFormat {
fun savePreferences(file: File, prefs: Prefs, masterPassword: String? = null) fun savePreferences(file: File, prefs: Prefs, masterPassword: String? = null)
fun loadPreferences(file: File, masterPassword: String? = null) : Prefs fun loadPreferences(file: File, masterPassword: String? = null): Prefs
fun loadMetadata(contents: String? = null): PrefMetadataMap
fun isPreferencesFile(file: File, preloadedContents: String? = null): Boolean
} }
enum class PrefsStatus(@DrawableRes val icon:Int) { enum class PrefsStatus(@DrawableRes val icon: Int) {
OK(R.drawable.ic_meta_ok), OK(R.drawable.ic_meta_ok),
WARN(R.drawable.ic_meta_warning), WARN(R.drawable.ic_meta_warning),
ERROR(R.drawable.ic_meta_error), ERROR(R.drawable.ic_meta_error),
@ -68,6 +74,11 @@ enum class PrefsStatus(@DrawableRes val icon:Int) {
DISABLED(R.drawable.ic_meta_error) DISABLED(R.drawable.ic_meta_error)
} }
enum class PrefsFormatsHandler {
CLASSIC,
ENCRYPTED
}
class PrefFileNotFoundError(message: String) : Exception(message) class PrefFileNotFoundError(message: String) : Exception(message)
class PrefIOError(message: String) : Exception(message) class PrefIOError(message: String) : Exception(message)
class PrefFormatError(message: String) : Exception(message) class PrefFormatError(message: String) : Exception(message)

View file

@ -57,6 +57,7 @@ import info.nightscout.androidaps.plugins.source.DexcomPlugin
import info.nightscout.androidaps.plugins.source.XdripPlugin import info.nightscout.androidaps.plugins.source.XdripPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.CommandQueue import info.nightscout.androidaps.queue.CommandQueue
import info.nightscout.androidaps.skins.SkinProvider
import info.nightscout.androidaps.utils.* import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.alertDialogs.OKDialog
import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelper
@ -64,41 +65,33 @@ import info.nightscout.androidaps.utils.extensions.toVisibility
import info.nightscout.androidaps.utils.protection.ProtectionCheck import info.nightscout.androidaps.utils.protection.ProtectionCheck
import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.sharedPreferences.SP import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.ui.UIRunnable
import info.nightscout.androidaps.utils.wizard.QuickWizard import info.nightscout.androidaps.utils.wizard.QuickWizard
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.overview_fragment.* import kotlinx.android.synthetic.main.overview_buttons_layout.*
import kotlinx.android.synthetic.main.overview_fragment.careportal_canulaage import kotlinx.android.synthetic.main.overview_buttons_layout.overview_carbsbutton
import kotlinx.android.synthetic.main.overview_fragment.careportal_insulinage import kotlinx.android.synthetic.main.overview_buttons_layout.overview_insulinbutton
import kotlinx.android.synthetic.main.overview_fragment.careportal_reservoirlevel import kotlinx.android.synthetic.main.overview_buttons_layout.overview_quickwizardbutton
import kotlinx.android.synthetic.main.overview_fragment.careportal_sensorage import kotlinx.android.synthetic.main.overview_buttons_layout.overview_treatmentbutton
import kotlinx.android.synthetic.main.overview_fragment.careportal_pbage import kotlinx.android.synthetic.main.overview_buttons_layout.overview_wizardbutton
import kotlinx.android.synthetic.main.overview_fragment.careportal_batterylevel
import kotlinx.android.synthetic.main.overview_fragment.overview_activeprofile
import kotlinx.android.synthetic.main.overview_fragment.overview_apsmode
import kotlinx.android.synthetic.main.overview_fragment.overview_arrow
import kotlinx.android.synthetic.main.overview_fragment.overview_basebasal
import kotlinx.android.synthetic.main.overview_fragment.overview_bg
import kotlinx.android.synthetic.main.overview_fragment.overview_bggraph
import kotlinx.android.synthetic.main.overview_fragment.overview_carbsbutton
import kotlinx.android.synthetic.main.overview_fragment.overview_chartMenuButton
import kotlinx.android.synthetic.main.overview_fragment.overview_cob
import kotlinx.android.synthetic.main.overview_fragment.overview_extendedbolus
import kotlinx.android.synthetic.main.overview_fragment.overview_insulinbutton
import kotlinx.android.synthetic.main.overview_fragment.overview_iob
import kotlinx.android.synthetic.main.overview_fragment.overview_iobcalculationprogess
import kotlinx.android.synthetic.main.overview_fragment.overview_iobgraph
import kotlinx.android.synthetic.main.overview_fragment.overview_looplayout
import kotlinx.android.synthetic.main.overview_fragment.overview_notifications import kotlinx.android.synthetic.main.overview_fragment.overview_notifications
import kotlinx.android.synthetic.main.overview_fragment.overview_pumpstatus
import kotlinx.android.synthetic.main.overview_fragment.overview_pumpstatuslayout
import kotlinx.android.synthetic.main.overview_fragment.overview_quickwizardbutton
import kotlinx.android.synthetic.main.overview_fragment.overview_sensitivity
import kotlinx.android.synthetic.main.overview_fragment.overview_temptarget
import kotlinx.android.synthetic.main.overview_fragment.overview_treatmentbutton
import kotlinx.android.synthetic.main.overview_fragment.overview_wizardbutton
import kotlinx.android.synthetic.main.overview_fragment_nsclient_tablet.* import kotlinx.android.synthetic.main.overview_fragment_nsclient_tablet.*
import kotlinx.android.synthetic.main.overview_graphs_layout.overview_bggraph
import kotlinx.android.synthetic.main.overview_graphs_layout.overview_chartMenuButton
import kotlinx.android.synthetic.main.overview_graphs_layout.overview_iobcalculationprogess
import kotlinx.android.synthetic.main.overview_graphs_layout.overview_iobgraph
import kotlinx.android.synthetic.main.overview_info_layout.*
import kotlinx.android.synthetic.main.overview_info_layout.overview_arrow
import kotlinx.android.synthetic.main.overview_info_layout.overview_basebasal
import kotlinx.android.synthetic.main.overview_info_layout.overview_bg
import kotlinx.android.synthetic.main.overview_info_layout.overview_cob
import kotlinx.android.synthetic.main.overview_info_layout.overview_extendedbolus
import kotlinx.android.synthetic.main.overview_info_layout.overview_iob
import kotlinx.android.synthetic.main.overview_info_layout.overview_sensitivity
import kotlinx.android.synthetic.main.overview_loop_pumpstatus_layout.*
import kotlinx.android.synthetic.main.overview_statuslights_layout.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -140,6 +133,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
@Inject lateinit var protectionCheck: ProtectionCheck @Inject lateinit var protectionCheck: ProtectionCheck
@Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var fabricPrivacy: FabricPrivacy
@Inject lateinit var overviewMenus: OverviewMenus @Inject lateinit var overviewMenus: OverviewMenus
@Inject lateinit var skinProvider: SkinProvider
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
@ -170,19 +164,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
smallHeight = screenHeight <= Constants.SMALL_HEIGHT smallHeight = screenHeight <= Constants.SMALL_HEIGHT
val landscape = screenHeight < screenWidth val landscape = screenHeight < screenWidth
return when { return inflater.inflate(skinProvider.activeSkin().overviewLayout(landscape, resourceHelper.gb(R.bool.isTablet), smallHeight), container, false)
resourceHelper.gb(R.bool.isTablet) && Config.NSCLIENT ->
inflater.inflate(R.layout.overview_fragment_nsclient_tablet, container, false)
Config.NSCLIENT ->
inflater.inflate(R.layout.overview_fragment_nsclient, container, false)
smallHeight || landscape ->
inflater.inflate(R.layout.overview_fragment_landscape, container, false)
else ->
inflater.inflate(R.layout.overview_fragment, container, false)
}
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -226,7 +208,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
super.onPause() super.onPause()
disposable.clear() disposable.clear()
loopHandler.removeCallbacksAndMessages(null) loopHandler.removeCallbacksAndMessages(null)
overview_apsmode?.let { unregisterForContextMenu(it) } overview_apsmode_llayout?.let { unregisterForContextMenu(it) }
overview_activeprofile?.let { unregisterForContextMenu(it) } overview_activeprofile?.let { unregisterForContextMenu(it) }
overview_temptarget?.let { unregisterForContextMenu(it) } overview_temptarget?.let { unregisterForContextMenu(it) }
} }
@ -300,7 +282,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} }
loopHandler.postDelayed(refreshLoop, 60 * 1000L) loopHandler.postDelayed(refreshLoop, 60 * 1000L)
overview_apsmode?.let { registerForContextMenu(overview_apsmode) } overview_apsmode_llayout?.let { registerForContextMenu(overview_apsmode) }
overview_activeprofile?.let { registerForContextMenu(it) } overview_activeprofile?.let { registerForContextMenu(it) }
overview_temptarget?.let { registerForContextMenu(it) } overview_temptarget?.let { registerForContextMenu(it) }
updateGUI("onResume") updateGUI("onResume")
@ -312,26 +294,20 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} }
override fun onContextItemSelected(item: MenuItem): Boolean { override fun onContextItemSelected(item: MenuItem): Boolean {
val manager = fragmentManager return if (overviewMenus.onContextItemSelected(item, childFragmentManager)) true else super.onContextItemSelected(item)
return if (manager != null && overviewMenus.onContextItemSelected(item, manager)) true else super.onContextItemSelected(item)
} }
override fun onClick(v: View) { override fun onClick(v: View) {
val manager = fragmentManager ?: return
// try to fix https://fabric.io/nightscout3/android/apps/info.nightscout.androidaps/issues/5aca7a1536c7b23527eb4be7?time=last-seven-days // try to fix https://fabric.io/nightscout3/android/apps/info.nightscout.androidaps/issues/5aca7a1536c7b23527eb4be7?time=last-seven-days
// https://stackoverflow.com/questions/14860239/checking-if-state-is-saved-before-committing-a-fragmenttransaction // https://stackoverflow.com/questions/14860239/checking-if-state-is-saved-before-committing-a-fragmenttransaction
if (manager.isStateSaved) return if (childFragmentManager.isStateSaved) return
activity?.let { activity -> activity?.let { activity ->
when (v.id) { when (v.id) {
R.id.overview_treatmentbutton -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, Runnable { TreatmentDialog().show(manager, "Overview") }) R.id.overview_treatmentbutton -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable(Runnable { TreatmentDialog().show(childFragmentManager, "Overview") }))
R.id.overview_wizardbutton -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, Runnable { WizardDialog().show(manager, "Overview") }) R.id.overview_wizardbutton -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable(Runnable { WizardDialog().show(childFragmentManager, "Overview") }))
R.id.overview_insulinbutton -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, Runnable { InsulinDialog().show(manager, "Overview") }) R.id.overview_insulinbutton -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable(Runnable { InsulinDialog().show(childFragmentManager, "Overview") }))
R.id.overview_quickwizardbutton -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, Runnable { onClickQuickWizard() }) R.id.overview_quickwizardbutton -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable(Runnable { onClickQuickWizard() }))
R.id.overview_carbsbutton -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, Runnable { CarbsDialog().show(manager, "Overview") }) R.id.overview_carbsbutton -> protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable(Runnable { CarbsDialog().show(childFragmentManager, "Overview") }))
R.id.overview_pumpstatus -> {
if (activePlugin.activePump.isSuspended || !activePlugin.activePump.isInitialized) commandQueue.readStatus("RefreshClicked", null)
}
R.id.overview_cgmbutton -> { R.id.overview_cgmbutton -> {
if (xdripPlugin.isEnabled(PluginType.BGSOURCE)) if (xdripPlugin.isEnabled(PluginType.BGSOURCE))
@ -346,7 +322,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
R.id.overview_calibrationbutton -> { R.id.overview_calibrationbutton -> {
if (xdripPlugin.isEnabled(PluginType.BGSOURCE)) { if (xdripPlugin.isEnabled(PluginType.BGSOURCE)) {
CalibrationDialog().show(manager, "CalibrationDialog") CalibrationDialog().show(childFragmentManager, "CalibrationDialog")
} else if (dexcomPlugin.isEnabled(PluginType.BGSOURCE)) { } else if (dexcomPlugin.isEnabled(PluginType.BGSOURCE)) {
try { try {
dexcomPlugin.findDexcomPackageName()?.let { dexcomPlugin.findDexcomPackageName()?.let {
@ -570,9 +546,9 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
val glucoseStatus = GlucoseStatus(injector).glucoseStatusData val glucoseStatus = GlucoseStatus(injector).glucoseStatusData
if (glucoseStatus != null) { if (glucoseStatus != null) {
overview_delta?.text = "Δ ${Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)} $units" overview_delta?.text = "Δ ${Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)}"
overview_deltashort?.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) overview_deltashort?.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
overview_avgdelta?.text = "øΔ15m: ${Profile.toUnitsString(glucoseStatus.short_avgdelta, glucoseStatus.short_avgdelta * Constants.MGDL_TO_MMOLL, units)}\nøΔ40m: ${Profile.toUnitsString(glucoseStatus.long_avgdelta, glucoseStatus.long_avgdelta * Constants.MGDL_TO_MMOLL, units)}" overview_avgdelta?.text = "Δ15m: ${Profile.toUnitsString(glucoseStatus.short_avgdelta, glucoseStatus.short_avgdelta * Constants.MGDL_TO_MMOLL, units)}\nΔ40m: ${Profile.toUnitsString(glucoseStatus.long_avgdelta, glucoseStatus.long_avgdelta * Constants.MGDL_TO_MMOLL, units)}"
} else { } else {
overview_delta?.text = "Δ " + resourceHelper.gs(R.string.notavailable) overview_delta?.text = "Δ " + resourceHelper.gs(R.string.notavailable)
overview_deltashort?.text = "---" overview_deltashort?.text = "---"
@ -597,53 +573,72 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
if (Config.APS && pump.pumpDescription.isTempBasalCapable) { if (Config.APS && pump.pumpDescription.isTempBasalCapable) {
overview_apsmode?.visibility = View.VISIBLE overview_apsmode?.visibility = View.VISIBLE
when { when {
loopPlugin.isEnabled(PluginType.LOOP) && loopPlugin.isSuperBolus -> { loopPlugin.isEnabled() && loopPlugin.isSuperBolus -> {
overview_apsmode?.text = String.format(resourceHelper.gs(R.string.loopsuperbolusfor), loopPlugin.minutesToEndOfSuspend()) overview_apsmode.setImageResource(R.drawable.loop_superbolus)
overview_apsmode?.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning)) overview_apsmode_text?.text = DateUtil.age(loopPlugin.minutesToEndOfSuspend() * 60000L, true, resourceHelper)
overview_apsmode?.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning)) //overview_apsmode_text?.text = String.format(resourceHelper.gs(R.string.loopsuperbolusfor), loopPlugin.minutesToEndOfSuspend())
// overview_apsmode_text?.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning))
// overview_apsmode_text?.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning))
} }
loopPlugin.isDisconnected -> { loopPlugin.isDisconnected -> {
overview_apsmode?.text = String.format(resourceHelper.gs(R.string.loopdisconnectedfor), loopPlugin.minutesToEndOfSuspend()) overview_apsmode.setImageResource(R.drawable.loop_disconnected)
overview_apsmode?.setBackgroundColor(resourceHelper.gc(R.color.ribbonCritical)) overview_apsmode_text?.text = DateUtil.age(loopPlugin.minutesToEndOfSuspend() * 60000L, true, resourceHelper)
overview_apsmode?.setTextColor(resourceHelper.gc(R.color.ribbonTextCritical)) // overview_apsmode_text?.text = String.format(resourceHelper.gs(R.string.loopdisconnectedfor), loopPlugin.minutesToEndOfSuspend())
// overview_apsmode_text?.setBackgroundColor(resourceHelper.gc(R.color.ribbonCritical))
// overview_apsmode_text?.setTextColor(resourceHelper.gc(R.color.ribbonTextCritical))
} }
loopPlugin.isEnabled(PluginType.LOOP) && loopPlugin.isSuspended -> { loopPlugin.isEnabled() && loopPlugin.isSuspended -> {
overview_apsmode?.text = String.format(resourceHelper.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend()) overview_apsmode.setImageResource(R.drawable.loop_paused)
overview_apsmode?.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning)) overview_apsmode_text?.text = DateUtil.age(loopPlugin.minutesToEndOfSuspend() * 60000L, true, resourceHelper)
overview_apsmode?.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning)) // overview_apsmode_text?.text = String.format(resourceHelper.gs(R.string.loopsuspendedfor), loopPlugin.minutesToEndOfSuspend())
// overview_apsmode_text?.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning))
// overview_apsmode_text?.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning))
} }
pump.isSuspended -> { pump.isSuspended -> {
overview_apsmode?.text = resourceHelper.gs(R.string.pumpsuspended) overview_apsmode.setImageResource(R.drawable.loop_paused)
overview_apsmode?.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning)) overview_apsmode_text?.text = ""
overview_apsmode?.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning)) // overview_apsmode_text?.text = resourceHelper.gs(R.string.pumpsuspended)
// overview_apsmode_text?.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning))
// overview_apsmode_text?.setTextColor(resourceHelper.gc(R.color.ribbonTextWarning))
} }
loopPlugin.isEnabled(PluginType.LOOP) -> { loopPlugin.isEnabled() && closedLoopEnabled.value() && loopPlugin.isLGS -> {
val isLGS = loopPlugin.isLGS overview_apsmode.setImageResource(R.drawable.loop_lgs)
overview_apsmode?.text = overview_apsmode_text?.text = ""
if (closedLoopEnabled.value()) // overview_apsmode_text?.text = resourceHelper.gs(R.string.closedloop)
if (isLGS) // overview_apsmode_text?.setBackgroundColor(resourceHelper.gc(R.color.ribbonDefault))
resourceHelper.gs(R.string.lgs) // overview_apsmode_text?.setTextColor(resourceHelper.gc(R.color.ribbonTextDefault))
else
resourceHelper.gs(R.string.closedloop)
else
resourceHelper.gs(R.string.openloop)
overview_apsmode?.setBackgroundColor(if (isLGS) resourceHelper.gc(R.color.ribbonUnusual) else resourceHelper.gc(R.color.ribbonDefault))
overview_apsmode?.setTextColor(resourceHelper.gc(R.color.ribbonTextDefault))
} }
else -> { loopPlugin.isEnabled() && closedLoopEnabled.value() -> {
overview_apsmode?.text = resourceHelper.gs(R.string.disabledloop) overview_apsmode.setImageResource(R.drawable.loop_closed)
overview_apsmode?.setBackgroundColor(resourceHelper.gc(R.color.ribbonCritical)) overview_apsmode_text?.text = ""
overview_apsmode?.setTextColor(resourceHelper.gc(R.color.ribbonTextCritical)) // overview_apsmode_text?.text = resourceHelper.gs(R.string.closedloop)
// overview_apsmode_text?.setBackgroundColor(resourceHelper.gc(R.color.ribbonDefault))
// overview_apsmode_text?.setTextColor(resourceHelper.gc(R.color.ribbonTextDefault))
}
loopPlugin.isEnabled() && !closedLoopEnabled.value() -> {
overview_apsmode.setImageResource(R.drawable.loop_open)
overview_apsmode_text?.text = ""
// overview_apsmode_text?.text = resourceHelper.gs(R.string.openloop)
// overview_apsmode_text?.setBackgroundColor(resourceHelper.gc(R.color.ribbonDefault))
// overview_apsmode_text?.setTextColor(resourceHelper.gc(R.color.ribbonTextDefault))
}
else -> {
overview_apsmode.setImageResource(R.drawable.loop_disabled)
overview_apsmode_text?.text = ""
// overview_apsmode_text?.text = resourceHelper.gs(R.string.disabledloop)
// overview_apsmode_text?.setBackgroundColor(resourceHelper.gc(R.color.ribbonCritical))
// overview_apsmode_text?.setTextColor(resourceHelper.gc(R.color.ribbonTextCritical))
} }
} }
} else { } else {
overview_apsmode?.visibility = View.GONE overview_apsmode_text?.visibility = View.GONE
} }
// temp target // temp target
@ -660,9 +655,9 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
// Basal, TBR // Basal, TBR
val activeTemp = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis()) val activeTemp = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis())
overview_basebasal?.text = activeTemp?.let { if (resourceHelper.shortTextMode()) "T: " + activeTemp.toStringVeryShort() else activeTemp.toStringFull() } overview_basebasal?.text = activeTemp?.let { if (resourceHelper.shortTextMode()) "T:" + activeTemp.toStringVeryShort() else activeTemp.toStringFull() }
?: resourceHelper.gs(R.string.pump_basebasalrate, profile.basal) ?: resourceHelper.gs(R.string.pump_basebasalrate, profile.basal)
overview_basebasal?.setOnClickListener { overview_basal_llayout?.setOnClickListener {
var fullText = "${resourceHelper.gs(R.string.pump_basebasalrate_label)}: ${resourceHelper.gs(R.string.pump_basebasalrate, profile.basal)}" var fullText = "${resourceHelper.gs(R.string.pump_basebasalrate_label)}: ${resourceHelper.gs(R.string.pump_basebasalrate, profile.basal)}"
if (activeTemp != null) if (activeTemp != null)
fullText += "\n" + resourceHelper.gs(R.string.pump_tempbasal_label) + ": " + activeTemp.toStringFull() fullText += "\n" + resourceHelper.gs(R.string.pump_tempbasal_label) + ": " + activeTemp.toStringFull()
@ -672,6 +667,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
} }
overview_basebasal?.setTextColor(activeTemp?.let { resourceHelper.gc(R.color.basal) } overview_basebasal?.setTextColor(activeTemp?.let { resourceHelper.gc(R.color.basal) }
?: resourceHelper.gc(R.color.defaulttextcolor)) ?: resourceHelper.gc(R.color.defaulttextcolor))
overview_basebasal_icon.setImageResource(if (activeTemp != null) R.drawable.icon_cp_basal_start else R.drawable.icon_cp_basal_end)
// Extended bolus // Extended bolus
val extendedBolus = treatmentsPlugin.getExtendedBolusFromHistory(System.currentTimeMillis()) val extendedBolus = treatmentsPlugin.getExtendedBolusFromHistory(System.currentTimeMillis())
@ -684,7 +680,9 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
OKDialog.show(it, resourceHelper.gs(R.string.extended_bolus), extendedBolus.toString()) OKDialog.show(it, resourceHelper.gs(R.string.extended_bolus), extendedBolus.toString())
} }
} }
overview_extended_llayout?.visibility = (extendedBolus != null && !pump.isFakingTempsByExtendedBoluses).toVisibility()
// Active profile
overview_activeprofile?.text = profileFunction.getProfileNameWithDuration() overview_activeprofile?.text = profileFunction.getProfileNameWithDuration()
if (profile.percentage != 100 || profile.timeshift != 0) { if (profile.percentage != 100 || profile.timeshift != 0) {
overview_activeprofile?.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning)) overview_activeprofile?.setBackgroundColor(resourceHelper.gc(R.color.ribbonWarning))
@ -702,23 +700,15 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
val bolusIob = treatmentsPlugin.lastCalculationTreatments.round() val bolusIob = treatmentsPlugin.lastCalculationTreatments.round()
val basalIob = treatmentsPlugin.lastCalculationTempBasals.round() val basalIob = treatmentsPlugin.lastCalculationTempBasals.round()
overview_iob?.text = when { overview_iob?.text = when {
resourceHelper.shortTextMode() -> { resourceHelper.shortTextMode() ->
resourceHelper.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob) resourceHelper.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob)
}
resourceHelper.gb(R.bool.isTablet) -> { else ->
resourceHelper.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob) + " (" +
resourceHelper.gs(R.string.bolus) + ": " + resourceHelper.gs(R.string.formatinsulinunits, bolusIob.iob) +
resourceHelper.gs(R.string.basal) + ": " + resourceHelper.gs(R.string.formatinsulinunits, basalIob.basaliob) + ")"
}
else -> {
resourceHelper.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob) + " (" + resourceHelper.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob) + " (" +
resourceHelper.gs(R.string.formatinsulinunits, bolusIob.iob) + "/" + resourceHelper.gs(R.string.formatinsulinunits, bolusIob.iob) + "/" +
resourceHelper.gs(R.string.formatinsulinunits, basalIob.basaliob) + ")" resourceHelper.gs(R.string.formatinsulinunits, basalIob.basaliob) + ")"
}
} }
overview_iob?.setOnClickListener { overview_iob_llayout?.setOnClickListener {
activity?.let { activity?.let {
OKDialog.show(it, resourceHelper.gs(R.string.iob), OKDialog.show(it, resourceHelper.gs(R.string.iob),
resourceHelper.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob) + "\n" + resourceHelper.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob) + "\n" +
@ -736,7 +726,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
var cobText: String = resourceHelper.gs(R.string.value_unavailable_short) var cobText: String = resourceHelper.gs(R.string.value_unavailable_short)
val cobInfo = iobCobCalculatorPlugin.getCobInfo(false, "Overview COB") val cobInfo = iobCobCalculatorPlugin.getCobInfo(false, "Overview COB")
if (cobInfo.displayCob != null) { if (cobInfo.displayCob != null) {
cobText = DecimalFormatter.to0Decimal(cobInfo.displayCob) cobText = resourceHelper.gs(R.string.format_carbs, cobInfo.displayCob.toInt())
if (cobInfo.futureCarbs > 0) cobText += "(" + DecimalFormatter.to0Decimal(cobInfo.futureCarbs) + ")" if (cobInfo.futureCarbs > 0) cobText += "(" + DecimalFormatter.to0Decimal(cobInfo.futureCarbs) + ")"
} }
overview_cob?.text = cobText overview_cob?.text = cobText
@ -757,9 +747,10 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
overview_uploader?.setOnClickListener { activity?.let { OKDialog.show(it, resourceHelper.gs(R.string.uploader), nsDeviceStatus.extendedUploaderStatus) } } overview_uploader?.setOnClickListener { activity?.let { OKDialog.show(it, resourceHelper.gs(R.string.uploader), nsDeviceStatus.extendedUploaderStatus) } }
// Sensitivity // Sensitivity
iobCobCalculatorPlugin.getLastAutosensData("Overview")?.let { autosensData -> overview_sensitivity?.text =
overview_sensitivity?.text = String.format(Locale.ENGLISH, "%.0f%%", autosensData.autosensResult.ratio * 100) iobCobCalculatorPlugin.getLastAutosensData("Overview")?.let { autosensData ->
} String.format(Locale.ENGLISH, "%.0f%%", autosensData.autosensResult.ratio * 100)
} ?: ""
// ****** GRAPH ******* // ****** GRAPH *******
GlobalScope.launch(Dispatchers.Main) { GlobalScope.launch(Dispatchers.Main) {

View file

@ -178,7 +178,7 @@ class LocalProfileFragment : DaggerFragment() {
localprofile_profileswitch.setOnClickListener { localprofile_profileswitch.setOnClickListener {
// TODO: select in dialog localProfilePlugin.currentProfileIndex // TODO: select in dialog localProfilePlugin.currentProfileIndex
fragmentManager?.let { ProfileSwitchDialog().show(it, "NewNSTreatmentDialog") } ProfileSwitchDialog().show(childFragmentManager, "NewNSTreatmentDialog")
} }
localprofile_reset.setOnClickListener { localprofile_reset.setOnClickListener {

View file

@ -71,21 +71,19 @@ class DanaRFragment : DaggerFragment() {
danar_history.setOnClickListener { startActivity(Intent(context, DanaRHistoryActivity::class.java)) } danar_history.setOnClickListener { startActivity(Intent(context, DanaRHistoryActivity::class.java)) }
danar_viewprofile.setOnClickListener { danar_viewprofile.setOnClickListener {
fragmentManager?.let { fragmentManager -> val profile = danaRPump.createConvertedProfile()?.getDefaultProfile()
val profile = danaRPump.createConvertedProfile()?.getDefaultProfile() ?: return@setOnClickListener
?: return@let val profileName = danaRPump.createConvertedProfile()?.getDefaultProfileName()
val profileName = danaRPump.createConvertedProfile()?.getDefaultProfileName() ?: return@setOnClickListener
?: return@let val args = Bundle()
val args = Bundle() args.putLong("time", DateUtil.now())
args.putLong("time", DateUtil.now()) args.putInt("mode", ProfileViewerDialog.Mode.CUSTOM_PROFILE.ordinal)
args.putInt("mode", ProfileViewerDialog.Mode.CUSTOM_PROFILE.ordinal) args.putString("customProfile", profile.data.toString())
args.putString("customProfile", profile.data.toString()) args.putString("customProfileUnits", profile.units)
args.putString("customProfileUnits", profile.units) args.putString("customProfileName", profileName)
args.putString("customProfileName", profileName) val pvd = ProfileViewerDialog()
val pvd = ProfileViewerDialog() pvd.arguments = args
pvd.arguments = args pvd.show(childFragmentManager, "ProfileViewDialog")
pvd.show(fragmentManager, "ProfileViewDialog")
}
} }
danar_stats.setOnClickListener { startActivity(Intent(context, TDDStatsActivity::class.java)) } danar_stats.setOnClickListener { startActivity(Intent(context, TDDStatsActivity::class.java)) }
danar_user_options.setOnClickListener { startActivity(Intent(context, DanaRUserOptionsActivity::class.java)) } danar_user_options.setOnClickListener { startActivity(Intent(context, DanaRUserOptionsActivity::class.java)) }

View file

@ -176,7 +176,7 @@ class OmnipodFragment : DaggerFragment() {
disposable += rxBus disposable += rxBus
.toObservable(EventPreferenceChange::class.java) .toObservable(EventPreferenceChange::class.java)
.observeOn(Schedulers.io()) .observeOn(Schedulers.io())
.subscribe({ event -> .subscribe({
setVisibilityOfPodDebugButton() setVisibilityOfPodDebugButton()
}, { fabricPrivacy.logException(it) }) }, { fabricPrivacy.logException(it) })
} }

View file

@ -619,15 +619,7 @@ public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPump
if (omnipodUtil.getPodSessionState() != null) { if (omnipodUtil.getPodSessionState() != null) {
podSessionState = omnipodUtil.getPodSessionState(); podSessionState = omnipodUtil.getPodSessionState();
} else { } else {
String podState = sp.getString(OmnipodConst.Prefs.PodState, ""); podSessionState = omnipodUtil.loadSessionState();
aapsLogger.info(LTag.PUMP, "PodSessionState-SP: loaded from SharedPreferences: " + podState);
if (StringUtils.isNotEmpty(podState)) {
podSessionState = omnipodUtil.getGsonInstance().fromJson(podState, PodSessionState.class);
podSessionState.injectDaggerClass(injector);
omnipodUtil.setPodSessionState(podSessionState);
}
} }

View file

@ -8,6 +8,7 @@ import com.google.gson.JsonDeserializer;
import com.google.gson.JsonPrimitive; import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializer; import com.google.gson.JsonSerializer;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.DateTimeZone; import org.joda.time.DateTimeZone;
import org.joda.time.format.ISODateTimeFormat; import org.joda.time.format.ISODateTimeFormat;
@ -15,10 +16,12 @@ import org.joda.time.format.ISODateTimeFormat;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R; import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.ActivePluginProvider;
import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.AAPSLogger;
import info.nightscout.androidaps.logging.LTag;
import info.nightscout.androidaps.plugins.bus.RxBusWrapper; import info.nightscout.androidaps.plugins.bus.RxBusWrapper;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
@ -46,6 +49,7 @@ public class OmnipodUtil {
private final OmnipodPumpStatus omnipodPumpStatus; private final OmnipodPumpStatus omnipodPumpStatus;
private final ActivePluginProvider activePlugins; private final ActivePluginProvider activePlugins;
private final SP sp; private final SP sp;
private final HasAndroidInjector injector;
private boolean lowLevelDebug = true; private boolean lowLevelDebug = true;
private OmnipodCommandType currentCommand; private OmnipodCommandType currentCommand;
@ -63,7 +67,8 @@ public class OmnipodUtil {
RileyLinkUtil rileyLinkUtil, RileyLinkUtil rileyLinkUtil,
OmnipodPumpStatus omnipodPumpStatus, OmnipodPumpStatus omnipodPumpStatus,
SP sp, SP sp,
ActivePluginProvider activePlugins ActivePluginProvider activePlugins,
HasAndroidInjector injector
) { ) {
this.aapsLogger = aapsLogger; this.aapsLogger = aapsLogger;
this.rxBus = rxBus; this.rxBus = rxBus;
@ -71,6 +76,7 @@ public class OmnipodUtil {
this.omnipodPumpStatus = omnipodPumpStatus; this.omnipodPumpStatus = omnipodPumpStatus;
this.sp = sp; this.sp = sp;
this.activePlugins = activePlugins; this.activePlugins = activePlugins;
this.injector = injector;
} }
@ -223,4 +229,20 @@ public class OmnipodUtil {
public SP getSp() { public SP getSp() {
return this.sp; return this.sp;
} }
public PodSessionState loadSessionState() {
String podState = sp.getString(OmnipodConst.Prefs.PodState, "");
aapsLogger.info(LTag.PUMP, "PodSessionState-SP: loaded from SharedPreferences: " + podState);
if (StringUtils.isNotEmpty(podState)) {
PodSessionState podSessionState = gsonInstance.fromJson(podState, PodSessionState.class);
podSessionState.injectDaggerClass(injector);
setPodSessionState(podSessionState);
return podSessionState;
}
return null;
}
} }

View file

@ -145,12 +145,10 @@ class TreatmentsBolusFragment : DaggerFragment() {
init { init {
calculation.setOnClickListener { calculation.setOnClickListener {
val treatment = it.tag as Treatment val treatment = it.tag as Treatment
fragmentManager?.let { fragmentManager -> if (treatment.getBoluscalc() != null) {
if (treatment.getBoluscalc() != null) { val wizardDialog = WizardInfoDialog()
val wizardDialog = WizardInfoDialog() wizardDialog.setData(treatment.getBoluscalc()!!)
wizardDialog.setData(treatment.getBoluscalc()!!) wizardDialog.show(childFragmentManager, "WizardInfoDialog")
wizardDialog.show(fragmentManager, "WizardInfoDialog")
}
} }
} }
calculation.paintFlags = calculation.paintFlags or Paint.UNDERLINE_TEXT_FLAG calculation.paintFlags = calculation.paintFlags or Paint.UNDERLINE_TEXT_FLAG

View file

@ -156,7 +156,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
args.putInt("mode", ProfileViewerDialog.Mode.RUNNING_PROFILE.ordinal) args.putInt("mode", ProfileViewerDialog.Mode.RUNNING_PROFILE.ordinal)
val pvd = ProfileViewerDialog() val pvd = ProfileViewerDialog()
pvd.arguments = args pvd.arguments = args
fragmentManager?.let { pvd.show(it, "ProfileViewDialog") } pvd.show(childFragmentManager, "ProfileViewDialog")
} }
} }
} }

View file

@ -0,0 +1,20 @@
package info.nightscout.androidaps.skins
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.R
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class SkinButtonsOn @Inject constructor() : SkinInterface {
override val description: Int get() = R.string.buttonson_desrciption
override fun overviewLayout(isLandscape: Boolean, isTablet: Boolean, isSmallHeight: Boolean): Int =
when {
Config.NSCLIENT && isTablet -> R.layout.overview_fragment_nsclient_tablet
Config.NSCLIENT -> R.layout.overview_fragment_nsclient
else -> R.layout.overview_fragment
}
}

View file

@ -0,0 +1,21 @@
package info.nightscout.androidaps.skins
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.R
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class SkinClassic @Inject constructor(): SkinInterface {
override val description: Int get() = R.string.classic_desrciption
override fun overviewLayout(isLandscape: Boolean, isTablet: Boolean, isSmallHeight: Boolean): Int =
when {
Config.NSCLIENT && isTablet -> R.layout.overview_fragment_nsclient_tablet
Config.NSCLIENT -> R.layout.overview_fragment_nsclient
isSmallHeight || isLandscape -> R.layout.overview_fragment_landscape
else -> R.layout.overview_fragment
}
}

View file

@ -0,0 +1,10 @@
package info.nightscout.androidaps.skins
import androidx.annotation.LayoutRes
import androidx.annotation.StringRes
interface SkinInterface {
@get:StringRes val description : Int
@LayoutRes fun overviewLayout(isLandscape : Boolean, isTablet : Boolean, isSmallHeight : Boolean): Int
}

View file

@ -0,0 +1,29 @@
package info.nightscout.androidaps.skins
import android.content.Context
import android.util.AttributeSet
import androidx.preference.ListPreference
import dagger.android.HasAndroidInjector
import java.util.*
import javax.inject.Inject
class SkinListPreference(context: Context, attrs: AttributeSet?)
: ListPreference(context, attrs) {
@Inject lateinit var skinProvider: SkinProvider
constructor(context: Context) : this(context, null)
init {
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
val entries = Vector<CharSequence>()
val values = Vector<CharSequence>()
for (skin in skinProvider.list) {
values.addElement(skin.javaClass.name)
entries.addElement(context.getString(skin.description))
}
entryValues = values.toTypedArray()
setEntries(entries.toTypedArray())
}
}

View file

@ -0,0 +1,22 @@
package info.nightscout.androidaps.skins
import info.nightscout.androidaps.R
import info.nightscout.androidaps.dependencyInjection.SkinsModule
import info.nightscout.androidaps.utils.sharedPreferences.SP
import okhttp3.internal.toImmutableMap
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class SkinProvider @Inject constructor(
val sp: SP,
@SkinsModule.Skin val allSkins: Map<@JvmSuppressWildcards Int, @JvmSuppressWildcards SkinInterface>
) {
fun activeSkin(): SkinInterface =
list.firstOrNull { it.javaClass.name == sp.getString(R.string.key_skin, "") }
?: list.first()
val list: List<SkinInterface>
get() = allSkins.toImmutableMap().toList().sortedBy { it.first }.map { it.second }
}

View file

@ -11,11 +11,18 @@ import java.text.DateFormat;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols; import java.text.DecimalFormatSymbols;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.EnumSet;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -270,6 +277,42 @@ public class DateUtil {
return TimeZone.getDefault().getOffset(timestamp) / 60000; return TimeZone.getDefault().getOffset(timestamp) / 60000;
} }
//Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}
public static Map<TimeUnit, Long> computeDiff(long date1, long date2) {
long diffInMillies = date2 - date1;
List<TimeUnit> units = new ArrayList<>(EnumSet.allOf(TimeUnit.class));
Collections.reverse(units);
Map<TimeUnit, Long> result = new LinkedHashMap<>();
long milliesRest = diffInMillies;
for (TimeUnit unit : units) {
long diff = unit.convert(milliesRest, TimeUnit.MILLISECONDS);
long diffInMilliesForUnit = unit.toMillis(diff);
milliesRest = milliesRest - diffInMilliesForUnit;
result.put(unit, diff);
}
return result;
}
public static String age(long milliseconds, boolean useShortText, ResourceHelper resourceHelper) {
Map<TimeUnit, Long> diff = computeDiff(0L, milliseconds);
String days = " " + resourceHelper.gs(R.string.days) + " ";
String hours = " " + resourceHelper.gs(R.string.hours) + " ";
String minutes = " " + resourceHelper.gs(R.string.unit_minutes) + " ";
if (useShortText) {
days = resourceHelper.gs(R.string.shortday);
hours = resourceHelper.gs(R.string.shorthour);
minutes = resourceHelper.gs(R.string.shortminute);
}
String result = "";
if (diff.get(TimeUnit.DAYS) > 0) result += diff.get(TimeUnit.DAYS) + days;
if (diff.get(TimeUnit.HOURS) > 0) result += diff.get(TimeUnit.HOURS) + hours;
if (diff.get(TimeUnit.DAYS) == 0) result += diff.get(TimeUnit.MINUTES) + minutes;
return result;
}
public static String niceTimeScalar(long t, ResourceHelper resourceHelper) { public static String niceTimeScalar(long t, ResourceHelper resourceHelper) {
String unit = resourceHelper.gs(R.string.unit_second); String unit = resourceHelper.gs(R.string.unit_second);
t = t / 1000; t = t / 1000;

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1,5 @@
<vector android:height="48dp" android:tint="#008585"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M16,17.01V10h-2v7.01h-3L15,21l4,-3.99h-3zM9,3L5,6.99h3V14h2V6.99h3L9,3z"/>
</vector>

View file

@ -0,0 +1,24 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="info.nightscout.androidaps.plugins.general.maintenance.activities.PrefImportListActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="4dp"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/importlist_recyclerview"
android:layout_width="match_parent"
android:scrollbars="vertical"
android:fadeScrollbars="true"
android:scrollbarStyle="outsideOverlay"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
</FrameLayout>

View file

@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/careportal_cardview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
card_view:cardBackgroundColor="?android:colorBackground">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="1dp"
android:layout_marginBottom="3dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="true"
android:orientation="horizontal">
<ImageView
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_marginStart="5dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="6dp"
android:layout_marginBottom="1dp"
android:src="@drawable/ic_meta_format"
android:tint="@color/importListFileName" />
<TextView
android:id="@+id/filelist_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="none"
android:maxLines="2"
android:paddingEnd="10dp"
android:scrollHorizontally="false"
android:text="File name here"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/importListFileName"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="true"
android:orientation="horizontal">
<TextView
android:id="@+id/filelist_dir"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="29dp"
android:layout_weight="1"
android:ellipsize="none"
android:maxLines="2"
android:paddingEnd="10dp"
android:scrollHorizontally="false"
android:text="File dir here"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/importListFileName"
android:textSize="11sp"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:id="@+id/metaline_name"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="6dp"
android:orientation="horizontal">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="30dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="1dp"
android:src="@drawable/ic_meta_name"
android:tint="@color/importListAdditionalInfo" />
<TextView
android:id="@+id/meta_device_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="exported on this Patient phone"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/importListAdditionalInfo"
tools:ignore="HardcodedText" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="3dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/meta_date_time_icon"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginStart="30dp"
android:layout_marginTop="1dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="1dp"
android:src="@drawable/ic_meta_date"
android:tint="@color/importListAdditionalInfo" />
<TextView
android:id="@+id/meta_date_time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="exported how long ago"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/importListAdditionalInfo"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/meta_app_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="v10.10.10.10"
android:textColor="@color/metadataTextWarning"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/meta_variant_format"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:text="FLAVOUR"
android:textColor="@color/metadataOk"
tools:ignore="HardcodedText" />
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="2dip"
android:layout_marginStart="5dp"
android:layout_marginTop="7dp"
android:layout_marginEnd="5dp"
android:layout_marginBottom="3dp"
android:background="@color/listdelimiter" />
</LinearLayout>
</androidx.cardview.widget.CardView>

View file

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/overview_buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_accepttempbutton"
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:text="@string/setbasalquestion"
android:textColor="@color/colorAcceptTempButton"
android:visibility="gone" />
<LinearLayout
android:id="@+id/overview_buttons_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="0dp"
android:paddingEnd="5dp" >
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_treatmentbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_insulin_carbs"
android:text="@string/overview_treatment_label"
android:textColor="@color/colorTreatmentButton"
android:textSize="10sp"
android:visibility="gone" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_insulinbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_bolus"
android:text="@string/overview_insulin_label"
android:textColor="@color/colorInsulinButton"
android:textSize="10sp" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_carbsbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_cp_bolus_carbs"
android:text="@string/overview_carbs_label"
android:textColor="@color/colorCarbsButton"
android:textSize="10sp" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_wizardbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_calculator"
android:text="@string/overview_calculator_label"
android:textColor="@color/colorCalculatorButton"
android:textSize="10sp" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_calibrationbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_calibration"
android:text="@string/overview_calibration"
android:textColor="@color/colorCalibrationButton"
android:textSize="10sp"
android:visibility="gone" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_cgmbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_xdrip"
android:text="@string/overview_cgm"
android:textColor="@color/colorCalibrationButton"
android:textSize="10sp"
android:visibility="gone" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_quickwizardbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_quickwizard"
android:text="@string/quickwizard"
android:textColor="@color/colorQuickWizardButton"
android:textSize="10sp" />
</LinearLayout>
</LinearLayout>

View file

@ -1,628 +1,39 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".plugins.general.overview.OverviewFragment"> tools:context=".plugins.general.overview.OverviewFragment">
<ScrollView <ScrollView
android:id="@+id/overview_toppart_scrollbar" android:id="@+id/overview_toppart_scrollbar"
android:layout_width="0dp" android:layout_weight="1"
android:layout_height="0dp" android:layout_width="wrap_content"
app:layout_constraintBottom_toTopOf="@id/overview_accepttempbutton" android:layout_height="0dp">
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/overview_notifications" android:id="@+id/overview_notifications"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/overview_looplayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.recyclerview.widget.RecyclerView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/overview_looplayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content" />
app:layout_constraintBottom_toTopOf="@+id/overview_pumpstatuslayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_notifications">
<TextView <include layout="@layout/overview_loop_pumpstatus_layout" />
android:id="@+id/overview_apsmode"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/openloop"
android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/overview_activeprofile"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<include layout="@layout/overview_info_layout" />
<TextView <include layout="@layout/overview_statuslights_layout" />
android:id="@+id/overview_activeprofile"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/profile"
android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/overview_temptarget"
app:layout_constraintStart_toEndOf="@+id/overview_apsmode"
app:layout_constraintTop_toTopOf="parent" />
<TextView <include layout="@layout/overview_graphs_layout" />
android:id="@+id/overview_temptarget"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/temptargetshort"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/mdtp_white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/overview_activeprofile"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </LinearLayout>
<LinearLayout
android:id="@+id/overview_pumpstatuslayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@+id/bg_tbr_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_looplayout">
<TextView
android:id="@+id/overview_pumpstatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/initializing"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bg_tbr_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@+id/overview_statuslights"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_pumpstatuslayout">
<TextView
android:id="@+id/overview_bg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00.0"
android:textSize="42sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/overview_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/overview_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:paddingStart="-2dp"
android:paddingEnd="0dp"
android:text="→"
android:textSize="28sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/overview_bg_guideline"
app:layout_constraintStart_toEndOf="@+id/overview_bg"
app:layout_constraintTop_toTopOf="@+id/overview_bg" />
<TextView
android:id="@+id/overview_hor_space"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" "
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/overview_bg_guideline"
app:layout_constraintStart_toEndOf="@+id/overview_arrow"
app:layout_constraintTop_toTopOf="@+id/overview_bg" />
<TextView
android:id="@+id/overview_timeago"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1 min ago"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@+id/overview_delta"
app:layout_constraintEnd_toEndOf="@+id/overview_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_bg" />
<TextView
android:id="@+id/overview_delta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="delta 15m: 0.3"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@+id/overview_avgdelta"
app:layout_constraintEnd_toEndOf="@+id/overview_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_timeago" />
<TextView
android:id="@+id/overview_avgdelta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="delta 40m: 0.3"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="@+id/overview_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_delta" />
<!-- right side -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/overview_bg_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/overview_iob_label"
app:layout_constraintGuide_percent="0.40"
app:layout_constraintStart_toEndOf="@+id/overview_hor_space"
app:layout_constraintTop_toTopOf="parent" />
<!-- right side IOB -->
<TextView
android:id="@+id/overview_iob_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/iob"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/overview_cob_label"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="parent" />
<TextView
android:id="@+id/overview_iob_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@+id/overview_iob_label"
app:layout_constraintTop_toTopOf="@+id/overview_iob_label" />
<TextView
android:id="@+id/overview_iob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="@string/iob"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_iob_label"
app:layout_constraintStart_toEndOf="@+id/overview_iob_colon" />
<!-- right side COB -->
<TextView
android:id="@+id/overview_cob_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cob"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/overview_basebasal_label"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="@+id/overview_iob_label" />
<TextView
android:id="@+id/overview_cob_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@+id/overview_cob_label"
app:layout_constraintTop_toBottomOf="@+id/overview_iob_label" />
<TextView
android:id="@+id/overview_cob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="@string/cob"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_cob_label"
app:layout_constraintStart_toEndOf="@+id/overview_cob_colon" />
<!-- right side basal -->
<TextView
android:id="@+id/overview_basebasal_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/basal_short"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/overview_extendedbolus_label"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="@+id/overview_cob_label" />
<TextView
android:id="@+id/overview_basebasal_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@+id/overview_basebasal_label"
app:layout_constraintTop_toBottomOf="@+id/overview_cob_label" />
<TextView
android:id="@+id/overview_basebasal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="0.50U/h @17:35 1/30min"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_basebasal_label"
app:layout_constraintStart_toEndOf="@+id/overview_basebasal_colon" />
<!-- right side extended -->
<TextView
android:id="@+id/overview_extendedbolus_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/extended_bolus_short"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/overview_sensitivity_label"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="@+id/overview_basebasal_label" />
<TextView
android:id="@+id/overview_extendedbolus_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="@+id/overview_extendedbolus_label"
app:layout_constraintStart_toEndOf="@+id/overview_extendedbolus_label" />
<TextView
android:id="@+id/overview_extendedbolus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="0.50U/h @17:35 1/30min"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_extendedbolus_label"
app:layout_constraintStart_toEndOf="@+id/overview_extendedbolus_colon" />
<!-- right side AS -->
<TextView
android:id="@+id/overview_sensitivity_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sensitivity_short"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="@+id/overview_extendedbolus_label" />
<TextView
android:id="@+id/overview_sensitivity_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="@+id/overview_sensitivity_label"
app:layout_constraintStart_toEndOf="@+id/overview_sensitivity_label" />
<TextView
android:id="@+id/overview_sensitivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="100%"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_sensitivity_label"
app:layout_constraintStart_toEndOf="@+id/overview_sensitivity_colon" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/overview_statuslights"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:layout_marginBottom="3dp"
android:background="?android:attr/colorControlHighlight"
android:orientation="horizontal"
android:paddingTop="4dp"
android:paddingBottom="4dp"
app:layout_constraintBottom_toTopOf="@+id/overview_bggraph"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bg_tbr_layout">
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_cp_age_canula" />
<TextView
android:id="@+id/careportal_canulaage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_cp_age_insulin" />
<TextView
android:id="@+id/careportal_insulinage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<TextView
android:id="@+id/careportal_reservoirlevel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_cp_age_sensor" />
<TextView
android:id="@+id/careportal_sensorage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_cp_age_battery" />
<TextView
android:id="@+id/careportal_pbage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="1dp"
android:textSize="14sp" />
<TextView
android:id="@+id/careportal_batterylevel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
</LinearLayout>
<com.jjoe64.graphview.GraphView
android:id="@+id/overview_bggraph"
android:layout_width="0dp"
android:layout_height="200dp"
app:layout_constraintBottom_toTopOf="@+id/overview_iobgraph"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_statuslights" />
<ImageButton
android:id="@+id/overview_chartMenuButton"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:contentDescription="@string/chartmenu"
app:layout_constraintEnd_toEndOf="@+id/overview_bggraph"
app:layout_constraintTop_toTopOf="@+id/overview_bggraph"
app:srcCompat="@drawable/ic_arrow_drop_down_white_24dp" />
<TextView
android:id="@+id/overview_iobcalculationprogess"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text=""
android:textSize="15sp"
app:layout_constraintBottom_toBottomOf="@+id/overview_bggraph"
app:layout_constraintEnd_toEndOf="@+id/overview_bggraph"
app:layout_constraintStart_toStartOf="@+id/overview_bggraph"
app:layout_constraintTop_toTopOf="@+id/overview_bggraph" />
<LinearLayout
android:id="@+id/overview_iobgraph"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/overview_bggraph" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView> </ScrollView>
<info.nightscout.androidaps.utils.SingleClickButton <include layout="@layout/overview_buttons_layout" />
android:id="@+id/overview_accepttempbutton"
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:text="@string/setbasalquestion"
android:textColor="@color/colorAcceptTempButton"
app:layout_constraintBottom_toTopOf="@id/overview_buttons_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/overview_toppart_scrollbar"
android:visibility="gone"/>
<LinearLayout </LinearLayout>
android:id="@+id/overview_buttons_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="0dp"
android:paddingEnd="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/overview_accepttempbutton">
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_treatmentbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_insulin_carbs"
android:text="@string/overview_treatment_label"
android:textColor="@color/colorTreatmentButton"
android:textSize="10sp"
android:visibility="gone" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_insulinbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_bolus"
android:text="@string/overview_insulin_label"
android:textColor="@color/colorInsulinButton"
android:textSize="10sp" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_carbsbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_cp_bolus_carbs"
android:text="@string/overview_carbs_label"
android:textColor="@color/colorCarbsButton"
android:textSize="10sp" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_wizardbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_calculator"
android:text="@string/overview_calculator_label"
android:textColor="@color/colorCalculatorButton"
android:textSize="10sp" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_calibrationbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_calibration"
android:text="@string/overview_calibration"
android:textColor="@color/colorCalibrationButton"
android:textSize="10sp"
android:visibility="gone" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_cgmbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_xdrip"
android:text="@string/overview_cgm"
android:textColor="@color/colorCalibrationButton"
android:textSize="10sp"
android:visibility="gone" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_quickwizardbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_quickwizard"
android:text="@string/quickwizard"
android:textColor="@color/colorQuickWizardButton"
android:textSize="10sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -1,628 +1,40 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".plugins.general.overview.OverviewFragment"> tools:context=".plugins.general.overview.OverviewFragment">
<ScrollView <ScrollView
android:id="@+id/overview_toppart_scrollbar" android:id="@+id/overview_toppart_scrollbar"
android:layout_width="0dp" android:layout_width="wrap_content"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent" android:layout_weight="1"
app:layout_constraintEnd_toEndOf="parent" tools:ignore="UselessParent">
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/overview_notifications" android:id="@+id/overview_notifications"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/overview_looplayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.recyclerview.widget.RecyclerView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/overview_looplayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content" />
app:layout_constraintBottom_toTopOf="@+id/overview_pumpstatuslayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_notifications">
<TextView <include layout="@layout/overview_loop_pumpstatus_layout" />
android:id="@+id/overview_apsmode"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/openloop"
android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/overview_activeprofile"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<include layout="@layout/overview_info_layout" />
<TextView <include layout="@layout/overview_statuslights_layout" />
android:id="@+id/overview_activeprofile"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/profile"
android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/overview_temptarget"
app:layout_constraintStart_toEndOf="@+id/overview_apsmode"
app:layout_constraintTop_toTopOf="parent" />
<TextView <include layout="@layout/overview_graphs_layout" />
android:id="@+id/overview_temptarget"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/temptargetshort"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/mdtp_white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/overview_activeprofile"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> <include layout="@layout/overview_buttons_layout" />
<LinearLayout </LinearLayout>
android:id="@+id/overview_pumpstatuslayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@+id/bg_tbr_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_looplayout">
<TextView
android:id="@+id/overview_pumpstatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/initializing"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bg_tbr_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@+id/overview_statuslights"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_pumpstatuslayout">
<TextView
android:id="@+id/overview_bg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00.0"
android:textSize="42sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/overview_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/overview_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:paddingStart="-2dp"
android:paddingEnd="0dp"
android:text="→"
android:textSize="28sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/overview_bg_guideline"
app:layout_constraintStart_toEndOf="@+id/overview_bg"
app:layout_constraintTop_toTopOf="@+id/overview_bg" />
<TextView
android:id="@+id/overview_hor_space"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" "
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/overview_bg_guideline"
app:layout_constraintStart_toEndOf="@+id/overview_arrow"
app:layout_constraintTop_toTopOf="@+id/overview_bg" />
<TextView
android:id="@+id/overview_timeago"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1 min ago"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@+id/overview_delta"
app:layout_constraintEnd_toEndOf="@+id/overview_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_bg" />
<TextView
android:id="@+id/overview_delta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="delta 15m: 0.3"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@+id/overview_avgdelta"
app:layout_constraintEnd_toEndOf="@+id/overview_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_timeago" />
<TextView
android:id="@+id/overview_avgdelta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="delta 40m: 0.3"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="@+id/overview_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_delta" />
<!-- right side -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/overview_bg_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/overview_iob_label"
app:layout_constraintGuide_percent="0.40"
app:layout_constraintStart_toEndOf="@+id/overview_hor_space"
app:layout_constraintTop_toTopOf="parent" />
<!-- right side IOB -->
<TextView
android:id="@+id/overview_iob_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/iob"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/overview_cob_label"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="parent" />
<TextView
android:id="@+id/overview_iob_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@+id/overview_iob_label"
app:layout_constraintTop_toTopOf="@+id/overview_iob_label" />
<TextView
android:id="@+id/overview_iob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="@string/iob"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_iob_label"
app:layout_constraintStart_toEndOf="@+id/overview_iob_colon" />
<!-- right side COB -->
<TextView
android:id="@+id/overview_cob_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cob"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/overview_basebasal_label"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="@+id/overview_iob_label" />
<TextView
android:id="@+id/overview_cob_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@+id/overview_cob_label"
app:layout_constraintTop_toBottomOf="@+id/overview_iob_label" />
<TextView
android:id="@+id/overview_cob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="@string/cob"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_cob_label"
app:layout_constraintStart_toEndOf="@+id/overview_cob_colon" />
<!-- right side basal -->
<TextView
android:id="@+id/overview_basebasal_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/basal_short"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/overview_extendedbolus_label"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="@+id/overview_cob_label" />
<TextView
android:id="@+id/overview_basebasal_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@+id/overview_basebasal_label"
app:layout_constraintTop_toBottomOf="@+id/overview_cob_label" />
<TextView
android:id="@+id/overview_basebasal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="0.50U/h @17:35 1/30min"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_basebasal_label"
app:layout_constraintStart_toEndOf="@+id/overview_basebasal_colon" />
<!-- right side extended -->
<TextView
android:id="@+id/overview_extendedbolus_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/extended_bolus_short"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/overview_sensitivity_label"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="@+id/overview_basebasal_label" />
<TextView
android:id="@+id/overview_extendedbolus_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="@+id/overview_extendedbolus_label"
app:layout_constraintStart_toEndOf="@+id/overview_extendedbolus_label" />
<TextView
android:id="@+id/overview_extendedbolus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="0.50U/h @17:35 1/30min"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_extendedbolus_label"
app:layout_constraintStart_toEndOf="@+id/overview_extendedbolus_colon" />
<!-- right side AS -->
<TextView
android:id="@+id/overview_sensitivity_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sensitivity_short"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="@+id/overview_extendedbolus_label" />
<TextView
android:id="@+id/overview_sensitivity_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="@+id/overview_sensitivity_label"
app:layout_constraintStart_toEndOf="@+id/overview_sensitivity_label" />
<TextView
android:id="@+id/overview_sensitivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="100%"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_sensitivity_label"
app:layout_constraintStart_toEndOf="@+id/overview_sensitivity_colon" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/overview_statuslights"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:layout_marginBottom="3dp"
android:background="?android:attr/colorControlHighlight"
android:orientation="horizontal"
android:paddingTop="4dp"
android:paddingBottom="4dp"
app:layout_constraintBottom_toTopOf="@+id/overview_bggraph"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bg_tbr_layout">
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_cp_age_canula" />
<TextView
android:id="@+id/careportal_canulaage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_cp_age_insulin" />
<TextView
android:id="@+id/careportal_insulinage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<TextView
android:id="@+id/careportal_reservoirlevel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_cp_age_sensor" />
<TextView
android:id="@+id/careportal_sensorage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_cp_age_battery" />
<TextView
android:id="@+id/careportal_pbage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="1dp"
android:textSize="14sp" />
<TextView
android:id="@+id/careportal_batterylevel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
</LinearLayout>
<com.jjoe64.graphview.GraphView
android:id="@+id/overview_bggraph"
android:layout_width="0dp"
android:layout_height="200dp"
app:layout_constraintBottom_toTopOf="@+id/overview_iobgraph"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_statuslights" />
<ImageButton
android:id="@+id/overview_chartMenuButton"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:contentDescription="@string/chartmenu"
app:layout_constraintEnd_toEndOf="@+id/overview_bggraph"
app:layout_constraintTop_toTopOf="@+id/overview_bggraph"
app:srcCompat="@drawable/ic_arrow_drop_down_white_24dp" />
<TextView
android:id="@+id/overview_iobcalculationprogess"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text=""
android:textSize="15sp"
app:layout_constraintBottom_toBottomOf="@+id/overview_bggraph"
app:layout_constraintEnd_toEndOf="@+id/overview_bggraph"
app:layout_constraintStart_toStartOf="@+id/overview_bggraph"
app:layout_constraintTop_toTopOf="@+id/overview_bggraph" />
<LinearLayout
android:id="@+id/overview_iobgraph"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@+id/overview_accepttempbutton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/overview_bggraph" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_accepttempbutton"
style="?android:attr/buttonStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:text="@string/setbasalquestion"
android:textColor="@color/colorAcceptTempButton"
app:layout_constraintBottom_toTopOf="@id/overview_buttons_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/overview_iobgraph"
android:visibility="gone"/>
<LinearLayout
android:id="@+id/overview_buttons_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="0dp"
android:paddingEnd="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/overview_accepttempbutton">
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_treatmentbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_insulin_carbs"
android:text="@string/overview_treatment_label"
android:textColor="@color/colorTreatmentButton"
android:textSize="10sp"
android:visibility="gone" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_insulinbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_bolus"
android:text="@string/overview_insulin_label"
android:textColor="@color/colorInsulinButton"
android:textSize="10sp" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_carbsbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_cp_bolus_carbs"
android:text="@string/overview_carbs_label"
android:textColor="@color/colorCarbsButton"
android:textSize="10sp" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_wizardbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_calculator"
android:text="@string/overview_calculator_label"
android:textColor="@color/colorCalculatorButton"
android:textSize="10sp" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_calibrationbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_calibration"
android:text="@string/overview_calibration"
android:textColor="@color/colorCalibrationButton"
android:textSize="10sp"
android:visibility="gone" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_cgmbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_xdrip"
android:text="@string/overview_cgm"
android:textColor="@color/colorCalibrationButton"
android:textSize="10sp"
android:visibility="gone" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_quickwizardbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_quickwizard"
android:text="@string/quickwizard"
android:textColor="@color/colorQuickWizardButton"
android:textSize="10sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView> </ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout> </LinearLayout>

View file

@ -1,466 +1,32 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".plugins.general.overview.OverviewFragment"> tools:context=".plugins.general.overview.OverviewFragment">
<ScrollView <ScrollView
android:id="@+id/overview_toppart_scrollbar" android:id="@+id/overview_toppart_scrollbar"
android:layout_width="0dp" android:layout_weight="1"
android:layout_height="0dp" android:layout_width="wrap_content"
app:layout_constraintBottom_toTopOf="@id/overview_buttons_layout" android:layout_height="0dp">
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/overview_notifications" android:id="@+id/overview_notifications"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/overview_looplayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.recyclerview.widget.RecyclerView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/overview_looplayout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content" />
app:layout_constraintBottom_toTopOf="@+id/overview_pumpstatuslayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_notifications">
<TextView <include layout="@layout/overview_loop_pumpstatus_layout" />
android:id="@+id/overview_apsmode"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/openloop"
android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/overview_activeprofile"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<include layout="@layout/overview_info_layout" />
<TextView <include layout="@layout/overview_statuslights_layout" />
android:id="@+id/overview_activeprofile"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/profile"
android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/overview_temptarget"
app:layout_constraintStart_toEndOf="@+id/overview_apsmode"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/overview_temptarget"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/temptargetshort"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/mdtp_white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/overview_activeprofile"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/overview_pumpstatuslayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@+id/bg_tbr_layout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_looplayout">
<TextView
android:id="@+id/overview_pumpstatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/initializing"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/bg_tbr_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@+id/overview_statuslights"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_pumpstatuslayout">
<TextView
android:id="@+id/overview_bg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00.0"
android:textSize="42sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/overview_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/overview_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:paddingStart="-2dp"
android:paddingEnd="0dp"
android:text="→"
android:textSize="28sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/overview_bg_guideline"
app:layout_constraintStart_toEndOf="@+id/overview_bg"
app:layout_constraintTop_toTopOf="@+id/overview_bg" />
<TextView
android:id="@+id/overview_hor_space"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=" "
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/overview_bg_guideline"
app:layout_constraintStart_toEndOf="@+id/overview_arrow"
app:layout_constraintTop_toTopOf="@+id/overview_bg" />
<TextView
android:id="@+id/overview_timeago"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1 min ago"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@+id/overview_delta"
app:layout_constraintEnd_toEndOf="@+id/overview_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_bg" />
<TextView
android:id="@+id/overview_delta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="delta 15m: 0.35"
android:textSize="14sp"
app:layout_constraintBottom_toTopOf="@+id/overview_avgdelta"
app:layout_constraintEnd_toEndOf="@+id/overview_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_timeago" />
<TextView
android:id="@+id/overview_avgdelta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="delta 40m: 0.1"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="@+id/overview_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_delta" />
<!-- right side -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/overview_bg_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/overview_iob_label"
app:layout_constraintGuide_percent="0.40"
app:layout_constraintStart_toEndOf="@+id/overview_hor_space"
app:layout_constraintTop_toTopOf="parent" />
<!-- right side IOB -->
<TextView
android:id="@+id/overview_iob_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/iob"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/overview_cob_label"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="parent" />
<TextView
android:id="@+id/overview_iob_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@+id/overview_iob_label"
app:layout_constraintTop_toTopOf="@+id/overview_iob_label" />
<TextView
android:id="@+id/overview_iob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="@string/iob"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_iob_label"
app:layout_constraintStart_toEndOf="@+id/overview_iob_colon" />
<!-- right side COB -->
<TextView
android:id="@+id/overview_cob_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/cob"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/overview_basebasal_label"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="@+id/overview_iob_label" />
<TextView
android:id="@+id/overview_cob_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@+id/overview_cob_label"
app:layout_constraintTop_toBottomOf="@+id/overview_iob_label" />
<TextView
android:id="@+id/overview_cob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="@string/cob"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_cob_label"
app:layout_constraintStart_toEndOf="@+id/overview_cob_colon" />
<!-- right side basal -->
<TextView
android:id="@+id/overview_basebasal_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/basal_short"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/overview_extendedbolus_label"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="@+id/overview_cob_label" />
<TextView
android:id="@+id/overview_basebasal_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintStart_toEndOf="@+id/overview_basebasal_label"
app:layout_constraintTop_toBottomOf="@+id/overview_cob_label" />
<TextView
android:id="@+id/overview_basebasal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="0.50U/h @17:35 1/30min"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_basebasal_label"
app:layout_constraintStart_toEndOf="@+id/overview_basebasal_colon" />
<!-- right side extended -->
<TextView
android:id="@+id/overview_extendedbolus_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/extended_bolus_short"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/overview_sensitivity_label"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="@+id/overview_basebasal_label" />
<TextView
android:id="@+id/overview_extendedbolus_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="@+id/overview_extendedbolus_label"
app:layout_constraintStart_toEndOf="@+id/overview_extendedbolus_label" />
<TextView
android:id="@+id/overview_extendedbolus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="0.50U/h @17:35 1/30min"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_extendedbolus_label"
app:layout_constraintStart_toEndOf="@+id/overview_extendedbolus_colon" />
<!-- right side AS -->
<TextView
android:id="@+id/overview_sensitivity_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/sensitivity_short"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/overview_bg_guideline"
app:layout_constraintTop_toBottomOf="@+id/overview_extendedbolus_label" />
<TextView
android:id="@+id/overview_sensitivity_colon"
android:layout_width="5dp"
android:layout_height="wrap_content"
android:text=":"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="@+id/overview_sensitivity_label"
app:layout_constraintStart_toEndOf="@+id/overview_sensitivity_label" />
<TextView
android:id="@+id/overview_sensitivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="100%"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/overview_sensitivity_label"
app:layout_constraintStart_toEndOf="@+id/overview_sensitivity_colon" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/overview_statuslights"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:layout_marginBottom="3dp"
android:background="?android:attr/colorControlHighlight"
android:orientation="horizontal"
android:paddingTop="4dp"
android:paddingBottom="4dp"
app:layout_constraintBottom_toTopOf="@+id/overview_bggraph"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/bg_tbr_layout">
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_cp_age_canula" />
<TextView
android:id="@+id/careportal_canulaage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_cp_age_insulin" />
<TextView
android:id="@+id/careportal_insulinage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<TextView
android:id="@+id/careportal_reservoirlevel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_cp_age_sensor" />
<TextView
android:id="@+id/careportal_sensorage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
<ImageView
android:layout_width="40dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:scaleType="centerInside"
android:src="@drawable/icon_cp_age_battery" />
<TextView
android:id="@+id/careportal_pbage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="1dp"
android:textSize="14sp" />
<TextView
android:id="@+id/careportal_batterylevel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="1dp"
android:paddingEnd="2dp"
android:textSize="14sp" />
</LinearLayout>
<TextView <TextView
android:id="@+id/overview_pump" android:id="@+id/overview_pump"
@ -470,189 +36,36 @@
android:paddingEnd="4sp" android:paddingEnd="4sp"
android:text="Pump: running" android:text="Pump: running"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:textSize="16sp" android:textSize="16sp" />
app:layout_constraintBottom_toTopOf="@+id/overview_openaps"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_statuslights" />
<TextView <TextView
android:id="@+id/overview_openaps" android:id="@+id/overview_openaps"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:paddingStart="4sp" android:paddingStart="4sp"
android:paddingEnd="4sp" android:paddingEnd="4sp"
android:text="OAPS: 3 min ago" android:text="OAPS: 3 min ago"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:textSize="16sp" android:textSize="16sp" />
app:layout_constraintBottom_toTopOf="@+id/overview_bggraph"
app:layout_constraintEnd_toStartOf="@+id/overview_uploader"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_pump" />
<TextView <TextView
android:id="@+id/overview_uploader" android:id="@+id/overview_uploader"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:gravity="end"
android:paddingStart="4sp" android:paddingStart="4sp"
android:paddingEnd="4sp" android:paddingEnd="4sp"
android:text="UPLD: 84%" android:text="UPLD: 84%"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:textSize="16sp" android:textSize="16sp" />
app:layout_constraintBottom_toTopOf="@+id/overview_bggraph"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/overview_openaps"
app:layout_constraintTop_toBottomOf="@+id/overview_pump" />
<com.jjoe64.graphview.GraphView <include layout="@layout/overview_graphs_layout" />
android:id="@+id/overview_bggraph"
android:layout_width="0dp"
android:layout_height="200dp"
app:layout_constraintBottom_toTopOf="@+id/overview_iobgraph"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_openaps" />
<ImageButton </LinearLayout>
android:id="@+id/overview_chartMenuButton"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginEnd="5dp"
android:contentDescription="@string/chartmenu"
app:layout_constraintEnd_toEndOf="@+id/overview_bggraph"
app:layout_constraintTop_toTopOf="@+id/overview_bggraph"
app:srcCompat="@drawable/ic_arrow_drop_down_white_24dp" />
<TextView
android:id="@+id/overview_iobcalculationprogess"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text=""
android:textSize="15sp"
app:layout_constraintBottom_toBottomOf="@+id/overview_bggraph"
app:layout_constraintEnd_toEndOf="@+id/overview_bggraph"
app:layout_constraintStart_toStartOf="@+id/overview_bggraph"
app:layout_constraintTop_toTopOf="@+id/overview_bggraph" />
<LinearLayout
android:id="@+id/overview_iobgraph"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/overview_bggraph" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView> </ScrollView>
<LinearLayout <include layout="@layout/overview_buttons_layout" />
android:id="@+id/overview_buttons_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="0dp"
android:paddingEnd="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/overview_toppart_scrollbar">
<info.nightscout.androidaps.utils.SingleClickButton </LinearLayout>
android:id="@+id/overview_treatmentbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_insulin_carbs"
android:text="@string/overview_treatment_label"
android:textColor="@color/colorTreatmentButton"
android:textSize="10sp"
android:visibility="gone" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_insulinbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_bolus"
android:text="@string/overview_insulin_label"
android:textColor="@color/colorInsulinButton"
android:textSize="10sp" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_carbsbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_cp_bolus_carbs"
android:text="@string/overview_carbs_label"
android:textColor="@color/colorCarbsButton"
android:textSize="10sp" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_wizardbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_calculator"
android:text="@string/overview_calculator_label"
android:textColor="@color/colorCalculatorButton"
android:textSize="10sp" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_calibrationbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_calibration"
android:text="@string/overview_calibration"
android:textColor="@color/colorCalibrationButton"
android:textSize="10sp"
android:visibility="gone" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_cgmbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_xdrip"
android:text="@string/overview_cgm"
android:textColor="@color/colorCalibrationButton"
android:textSize="10sp"
android:visibility="gone" />
<info.nightscout.androidaps.utils.SingleClickButton
android:id="@+id/overview_quickwizardbutton"
style="?android:attr/buttonStyle"
android:layout_width="0px"
android:layout_height="fill_parent"
android:layout_marginEnd="-4dp"
android:layout_weight="0.5"
android:drawableTop="@drawable/icon_quickwizard"
android:text="@string/quickwizard"
android:textColor="@color/colorQuickWizardButton"
android:textSize="10sp" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -27,82 +27,7 @@
</androidx.recyclerview.widget.RecyclerView> </androidx.recyclerview.widget.RecyclerView>
<androidx.constraintlayout.widget.ConstraintLayout <include layout="@layout/overview_loop_pumpstatus_layout" />
android:id="@+id/overview_looplayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/overview_pumpstatuslayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_notifications">
<TextView
android:id="@+id/overview_apsmode"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/openloop"
android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/overview_activeprofile"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/overview_activeprofile"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/profile"
android:textAppearance="?android:attr/textAppearanceSmall"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/overview_temptarget"
app:layout_constraintStart_toEndOf="@+id/overview_apsmode"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/overview_temptarget"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/temptargetshort"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/mdtp_white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/overview_activeprofile"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/overview_pumpstatuslayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingTop="2dp">
<TextView
android:id="@+id/overview_pumpstatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:gravity="center_vertical|center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="@string/initializing"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View file

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1">
<com.jjoe64.graphview.GraphView
android:id="@+id/overview_bggraph"
android:layout_width="wrap_content"
android:layout_height="200dp" />
<ImageButton
android:id="@+id/overview_chartMenuButton"
android:layout_width="30dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:contentDescription="@string/chartmenu"
android:paddingTop="5dp"
app:srcCompat="@drawable/ic_arrow_drop_down_white_24dp" />
<TextView
android:id="@+id/overview_iobcalculationprogess"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
</RelativeLayout>
<LinearLayout
android:id="@+id/overview_iobgraph"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
</LinearLayout>

View file

@ -0,0 +1,242 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/info_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="@+id/overview_bg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="00.0"
android:textSize="60sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/overview_arrow"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/overview_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:paddingStart="-2dp"
android:paddingEnd="0dp"
android:text="→"
android:textSize="42sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@+id/overview_deltas_llayout"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toEndOf="@+id/overview_bg"
app:layout_constraintTop_toTopOf="@+id/overview_bg" />
<LinearLayout
android:id="@+id/overview_deltas_llayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@+id/overview_apsmode_llayout"
app:layout_constraintStart_toEndOf="@+id/overview_arrow"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/overview_timeago"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
<TextView
android:id="@+id/overview_delta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
<TextView
android:id="@+id/overview_avgdelta"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Small" />
</LinearLayout>
<LinearLayout
android:id="@+id/overview_apsmode_llayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/overview_deltas_llayout"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/overview_apsmode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="-4dp"
android:src="@drawable/loop_closed" />
<TextView
android:id="@+id/overview_apsmode_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="Open Loop"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:id="@+id/overview_iob_llayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@+id/overview_cob_llayout"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/overview_bg">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/icon_bolus" />
<TextView
android:id="@+id/overview_iob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:id="@+id/overview_cob_llayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@+id/overview_basal_llayout"
app:layout_constraintStart_toEndOf="@+id/overview_iob_llayout"
app:layout_constraintTop_toBottomOf="@+id/overview_bg">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/icon_cp_bolus_carbs" />
<TextView
android:id="@+id/overview_cob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:id="@+id/overview_basal_llayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@+id/overview_extended_llayout"
app:layout_constraintStart_toEndOf="@+id/overview_cob_llayout"
app:layout_constraintTop_toBottomOf="@+id/overview_bg">
<ImageView
android:id="@+id/overview_basebasal_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/icon_cp_basal_start" />
<TextView
android:id="@+id/overview_basebasal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:id="@+id/overview_extended_llayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toStartOf="@+id/overview_as_llayout"
app:layout_constraintStart_toEndOf="@+id/overview_basal_llayout"
app:layout_constraintTop_toBottomOf="@+id/overview_bg">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/icon_actions_startextbolus" />
<TextView
android:id="@+id/overview_extendedbolus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:id="@+id/overview_as_llayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/overview_extended_llayout"
app:layout_constraintTop_toBottomOf="@+id/overview_bg">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/ic_swap_vert_black_48dp_green" />
<TextView
android:id="@+id/overview_sensitivity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="3dp"
android:paddingBottom="3dp"
android:text="n/a"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textStyle="bold" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Some files were not shown because too many files have changed in this diff Show more