Merge branch 'dev' into aidex_support_v2
This commit is contained in:
commit
e82c6976fd
721 changed files with 11616 additions and 7511 deletions
|
@ -44,5 +44,5 @@ Hints
|
||||||
* Start small, it is easier to review smaller changes that affect fewer parts of code
|
* Start small, it is easier to review smaller changes that affect fewer parts of code
|
||||||
* Take a look into Issues list (https://github.com/nightscout/AndroidAPS/issues) - maybe there is something you can fix or implement
|
* Take a look into Issues list (https://github.com/nightscout/AndroidAPS/issues) - maybe there is something you can fix or implement
|
||||||
* For new features, make sure there is Issue to track progress and have on-topic discussion
|
* For new features, make sure there is Issue to track progress and have on-topic discussion
|
||||||
* Reach out to community, discuss idea on Gitter (https://gitter.im/MilosKozak/AndroidAPS)
|
* Reach out to community, discuss idea on Discord (https://discord.gg/4fQUWHZ4Mw)
|
||||||
* Speak with other developers to minimise merge conflicts. Find out who worked, working or plan to work on speciffic issue or part of app
|
* Speak with other developers to minimise merge conflicts. Find out who worked, working or plan to work on speciffic issue or part of app
|
||||||
|
|
|
@ -109,7 +109,7 @@ android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
versionCode 1500
|
versionCode 1500
|
||||||
version "3.0.0.1-dev-aidex"
|
version "3.0.0.1-dev-i"
|
||||||
buildConfigField "String", "VERSION", '"' + version + '"'
|
buildConfigField "String", "VERSION", '"' + version + '"'
|
||||||
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"'
|
||||||
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'
|
buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"'
|
||||||
|
@ -167,9 +167,6 @@ android {
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
flatDir {
|
|
||||||
dirs 'libs'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,14 +41,35 @@
|
||||||
<application
|
<application
|
||||||
android:name=".MainApp"
|
android:name=".MainApp"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
android:backupAgent=".utils.SPBackupAgent"
|
||||||
|
android:fullBackupOnly="false"
|
||||||
android:icon="${appIcon}"
|
android:icon="${appIcon}"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
|
android:restoreAnyVersion="true"
|
||||||
android:roundIcon="${appIconRound}"
|
android:roundIcon="${appIconRound}"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme.Launcher"
|
android:theme="@style/AppTheme.Launcher" >
|
||||||
android:fullBackupOnly="false"
|
|
||||||
android:backupAgent=".utils.SPBackupAgent"
|
<activity
|
||||||
android:restoreAnyVersion="true">
|
android:name=".widget.WidgetConfigureActivity"
|
||||||
|
android:theme="@android:style/Theme.Material.Dialog.NoActionBar"
|
||||||
|
android:exported="true">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name=".widget.Widget"
|
||||||
|
android:exported="true" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/widget_info" />
|
||||||
|
</receiver>
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.android.backup.api_key"
|
android:name="com.google.android.backup.api_key"
|
||||||
|
@ -59,6 +80,7 @@
|
||||||
android:resource="@xml/automotive_app_desc" />
|
android:resource="@xml/automotive_app_desc" />
|
||||||
|
|
||||||
<activity android:name=".MainActivity"
|
<activity android:name=".MainActivity"
|
||||||
|
android:theme="@style/AppTheme"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
@ -76,12 +98,18 @@
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".plugins.general.maintenance.activities.PrefImportListActivity" />
|
<activity android:name=".plugins.general.maintenance.activities.PrefImportListActivity"
|
||||||
<activity android:name=".activities.HistoryBrowseActivity" />
|
android:theme="@style/AppTheme" />
|
||||||
<activity android:name=".activities.TreatmentsActivity" />
|
<activity android:name=".activities.HistoryBrowseActivity"
|
||||||
<activity android:name=".activities.SurveyActivity" />
|
android:theme="@style/AppTheme" />
|
||||||
<activity android:name=".activities.ProfileHelperActivity" />
|
<activity android:name=".activities.TreatmentsActivity"
|
||||||
<activity android:name=".activities.StatsActivity" />
|
android:theme="@style/AppTheme" />
|
||||||
|
<activity android:name=".activities.SurveyActivity"
|
||||||
|
android:theme="@style/AppTheme" />
|
||||||
|
<activity android:name=".activities.ProfileHelperActivity"
|
||||||
|
android:theme="@style/AppTheme" />
|
||||||
|
<activity android:name=".activities.StatsActivity"
|
||||||
|
android:theme="@style/AppTheme" />
|
||||||
<activity
|
<activity
|
||||||
android:name="com.google.firebase.auth.internal.FederatedSignInActivity"
|
android:name="com.google.firebase.auth.internal.FederatedSignInActivity"
|
||||||
android:excludeFromRecents="true"
|
android:excludeFromRecents="true"
|
||||||
|
@ -125,9 +153,6 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<!-- Receiver keep alive, scheduled every 30 min -->
|
|
||||||
<receiver android:name=".receivers.KeepAliveReceiver" />
|
|
||||||
|
|
||||||
<!-- Receive ignore 5m, 15m, 30m requests for carb notifications -->
|
<!-- Receive ignore 5m, 15m, 30m requests for carb notifications -->
|
||||||
<receiver android:name=".plugins.aps.loop.CarbSuggestionReceiver" />
|
<receiver android:name=".plugins.aps.loop.CarbSuggestionReceiver" />
|
||||||
|
|
||||||
|
@ -235,6 +260,7 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".setupwizard.SetupWizardActivity"
|
android:name=".setupwizard.SetupWizardActivity"
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||||
|
android:theme="@style/AppTheme"
|
||||||
android:label="@string/title_activity_setup_wizard" />
|
android:label="@string/title_activity_setup_wizard" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
|
|
@ -202,161 +202,194 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
||||||
halfBasalTarget = 160; // when temptarget is 160 mg/dL, run 50% basal (120 = 75%; 140 = 60%)
|
halfBasalTarget = 160; // when temptarget is 160 mg/dL, run 50% basal (120 = 75%; 140 = 60%)
|
||||||
// 80 mg/dL with low_temptarget_lowers_sensitivity would give 1.5x basal, but is limited to autosens_max (1.2x by default)
|
// 80 mg/dL with low_temptarget_lowers_sensitivity would give 1.5x basal, but is limited to autosens_max (1.2x by default)
|
||||||
}
|
}
|
||||||
if ( high_temptarget_raises_sensitivity && profile.temptargetSet && target_bg > normalTarget
|
|
||||||
|| profile.low_temptarget_lowers_sensitivity && profile.temptargetSet && target_bg < normalTarget ) {
|
|
||||||
// w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44
|
|
||||||
// e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6
|
|
||||||
//sensitivityRatio = 2/(2+(target_bg-normalTarget)/40);
|
|
||||||
var c = halfBasalTarget - normalTarget;
|
|
||||||
sensitivityRatio = c/(c+target_bg-normalTarget);
|
|
||||||
// limit sensitivityRatio to profile.autosens_max (1.2x by default)
|
|
||||||
sensitivityRatio = Math.min(sensitivityRatio, profile.autosens_max);
|
|
||||||
sensitivityRatio = round(sensitivityRatio,2);
|
|
||||||
console.log("Sensitivity ratio set to "+sensitivityRatio+" based on temp target of "+target_bg+"; ");
|
|
||||||
} else if (typeof autosens_data !== 'undefined' && autosens_data) {
|
|
||||||
sensitivityRatio = autosens_data.ratio;
|
|
||||||
console.log("Autosens ratio: "+sensitivityRatio+"; ");
|
|
||||||
}
|
|
||||||
if (sensitivityRatio) {
|
|
||||||
basal = profile.current_basal * sensitivityRatio;
|
|
||||||
basal = round_basal(basal, profile);
|
|
||||||
if (basal !== profile_current_basal) {
|
|
||||||
console.log("Adjusting basal from "+profile_current_basal+" to "+basal+"; ");
|
|
||||||
} else {
|
|
||||||
console.log("Basal unchanged: "+basal+"; ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// adjust min, max, and target BG for sensitivity, such that 50% increase in ISF raises target from 100 to 120
|
|
||||||
if (profile.temptargetSet) {
|
|
||||||
//console.log("Temp Target set, not adjusting with autosens; ");
|
|
||||||
} else if (typeof autosens_data !== 'undefined' && autosens_data) {
|
|
||||||
if ( profile.sensitivity_raises_target && autosens_data.ratio < 1 || profile.resistance_lowers_target && autosens_data.ratio > 1 ) {
|
|
||||||
// with a target of 100, default 0.7-1.2 autosens min/max range would allow a 93-117 target range
|
|
||||||
min_bg = round((min_bg - 60) / autosens_data.ratio) + 60;
|
|
||||||
max_bg = round((max_bg - 60) / autosens_data.ratio) + 60;
|
|
||||||
var new_target_bg = round((target_bg - 60) / autosens_data.ratio) + 60;
|
|
||||||
// don't allow target_bg below 80
|
|
||||||
new_target_bg = Math.max(80, new_target_bg);
|
|
||||||
if (target_bg === new_target_bg) {
|
|
||||||
console.log("target_bg unchanged: "+new_target_bg+"; ");
|
|
||||||
} else {
|
|
||||||
console.log("target_bg from "+target_bg+" to "+new_target_bg+"; ");
|
|
||||||
}
|
|
||||||
target_bg = new_target_bg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof iob_data === 'undefined' ) {
|
|
||||||
rT.error ='Error: iob_data undefined. ';
|
|
||||||
return rT;
|
|
||||||
}
|
|
||||||
|
|
||||||
var iobArray = iob_data;
|
|
||||||
if (typeof(iob_data.length) && iob_data.length > 1) {
|
|
||||||
iob_data = iobArray[0];
|
|
||||||
//console.error(JSON.stringify(iob_data[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof iob_data.activity === 'undefined' || typeof iob_data.iob === 'undefined' ) {
|
|
||||||
rT.error ='Error: iob_data missing some property. ';
|
|
||||||
return rT;
|
|
||||||
}
|
|
||||||
|
|
||||||
var tick;
|
|
||||||
|
|
||||||
if (glucose_status.delta > -0.5) {
|
|
||||||
tick = "+" + round(glucose_status.delta,0);
|
|
||||||
} else {
|
|
||||||
tick = round(glucose_status.delta,0);
|
|
||||||
}
|
|
||||||
//var minDelta = Math.min(glucose_status.delta, glucose_status.short_avgdelta, glucose_status.long_avgdelta);
|
|
||||||
var minDelta = Math.min(glucose_status.delta, glucose_status.short_avgdelta);
|
|
||||||
var minAvgDelta = Math.min(glucose_status.short_avgdelta, glucose_status.long_avgdelta);
|
|
||||||
var maxDelta = Math.max(glucose_status.delta, glucose_status.short_avgdelta, glucose_status.long_avgdelta);
|
|
||||||
|
|
||||||
var profile_sens = round(profile.sens,1)
|
var profile_sens = round(profile.sens,1)
|
||||||
var sens = profile.sens;
|
var sens = profile.sens;
|
||||||
|
|
||||||
var now = new Date().getHours();
|
var now = new Date().getHours();
|
||||||
if (now < 1){
|
if (now < 1){
|
||||||
now = 1;}
|
now = 1;}
|
||||||
else {
|
else {
|
||||||
console.error("Time now is "+now+"; ");
|
console.error("Time now is "+now+"; ");
|
||||||
}
|
}
|
||||||
console.error(" ");
|
//*********************************************************************************
|
||||||
console.error("++++++++++++++++++++++++++++++++++++++++++++++++++++++");
|
//** Start of Dynamic ISF code for predictions **
|
||||||
console.error("++ Dynamic ISF Beta 1.4 - Linear Extrapolation/TDD7 ++");
|
//*********************************************************************************
|
||||||
console.error("++++++++++++++++++++++++++++++++++++++++++++++++++++++");
|
|
||||||
console.error(" ");
|
|
||||||
|
|
||||||
if (meal_data.TDDAIMI7){
|
console.error("---------------------------------------------------------");
|
||||||
var tdd7 = meal_data.TDDAIMI7;
|
console.error( " Dynamic ISF version Beta 1.5 ");
|
||||||
|
console.error("---------------------------------------------------------");
|
||||||
|
|
||||||
|
|
||||||
|
if (meal_data.TDDAIMI7){
|
||||||
|
var tdd7 = meal_data.TDDAIMI7;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
var tdd7 = ((basal * 12)*100)/21;
|
var tdd7 = ((basal * 12)*100)/21;
|
||||||
}
|
}
|
||||||
console.error("7-day average TDD is: " +tdd7+ "; ");
|
console.error("7-day average TDD is: " +tdd7+ "; ");
|
||||||
console.error(" ");
|
|
||||||
|
|
||||||
if (meal_data.TDDLast24){
|
if (meal_data.TDDLast24){
|
||||||
var tdd_24 = meal_data.TDDLast24;
|
var tdd_24 = meal_data.TDDLast24;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var tdd_24 = (( basal * 24 ) * 2.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (meal_data.TDDPUMP){
|
||||||
|
var tdd_pump = ( (meal_data.TDDPUMP / now ) * 24);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var tdd_pump = (( basal * 24 ) * 2.8);
|
||||||
|
}
|
||||||
|
console.log("Rolling TDD for last 24 hours is: "+tdd_24+"; ");
|
||||||
|
|
||||||
|
/*var tdd_pump_now = meal_data.TDDPUMP;
|
||||||
|
var tdd_pump = ( tdd_pump_now / (now / 24));*/
|
||||||
|
var TDD = (tdd7 * 0.4) + (tdd_pump * 0.6);
|
||||||
|
|
||||||
|
console.error("Pump extrapolated TDD = "+tdd_pump+"; ");
|
||||||
|
//if (tdd7 > 0){
|
||||||
|
if ( tdd_pump > tdd7 && now < 5 || now < 7 && TDD < ( 0.8 * tdd7 ) ){
|
||||||
|
TDD = ( 0.8 * tdd7 );
|
||||||
|
console.log("Excess or too low insulin from pump so TDD set to "+TDD+" based on 75% of TDD7; ");
|
||||||
|
rT.reason += "TDD: " +TDD+ " due to low or high tdd from pump; ";
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (tdd_pump > (1.75 * tdd7)){
|
||||||
|
TDD = tdd7;
|
||||||
|
console.error("TDD set to TDD7 due to high pump usage reported. TDD = "+TDD+"; ");
|
||||||
|
rT.reason += "TDD set to TDD7 due to high pump usage reported. TDD = "+TDD+"; ";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
else if (tdd_pump < (0.33 * tdd7)){
|
||||||
|
TDD = (tdd7 * 0.25) + (tdd_pump * 0.75);
|
||||||
|
console.error("TDD weighted to pump due to low insulin usage. TDD = "+TDD+"; ");
|
||||||
|
rT.reason += "TDD weighted to pump due to low insulin usage. TDD = "+TDD+"; ";
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
console.log("TDD = " +TDD+ " based on standard pump 60/tdd7 40 split; ");
|
||||||
|
rT.reason += "TDD: " +TDD+ " based on standard pump 60/tdd7 40 split; ";
|
||||||
|
}
|
||||||
|
|
||||||
|
var dynISFadjust = profile.DynISFAdjust;
|
||||||
|
var dynISFadjust = ( dynISFadjust / 100 );
|
||||||
|
var TDD = (dynISFadjust * TDD);
|
||||||
|
var variable_sens = (277700 / ( TDD * bg));
|
||||||
|
variable_sens = round(variable_sens,1);
|
||||||
|
if (dynISFadjust > 1 ) {
|
||||||
|
console.log("TDD adjustment factor is: " +dynISFadjust+"; ");
|
||||||
|
console.log("TDD adjusted to "+TDD+" using adjustment factor of "+dynISFadjust+"; ");
|
||||||
|
console.log("Current sensitivity for predictions is " +variable_sens+" based on current bg");
|
||||||
}
|
}
|
||||||
else {
|
else if (dynISFadjust < 1 ){
|
||||||
var tdd_24 = (( basal * 24 ) * 2.8);
|
console.log("TDD adjustment factor is: " +dynISFadjust+"; ");
|
||||||
|
console.log("TDD adjusted to "+TDD+" using adjustment factor of "+dynISFadjust+"; ");
|
||||||
|
console.log("Current sensitivity for predictions is " +variable_sens+" based on current bg");
|
||||||
|
} else {
|
||||||
|
console.log("Current sensitivity for predictions is " +variable_sens+" based on current bg");
|
||||||
|
}
|
||||||
|
sens = variable_sens;
|
||||||
|
|
||||||
|
//*********************************************************************************
|
||||||
|
//** End of Dynamic ISF code for predictions **
|
||||||
|
//*********************************************************************************
|
||||||
|
|
||||||
|
|
||||||
|
if ( high_temptarget_raises_sensitivity && profile.temptargetSet && target_bg > normalTarget || profile.low_temptarget_lowers_sensitivity && profile.temptargetSet && target_bg < normalTarget ) {
|
||||||
|
// w/ target 100, temp target 110 = .89, 120 = 0.8, 140 = 0.67, 160 = .57, and 200 = .44
|
||||||
|
// e.g.: Sensitivity ratio set to 0.8 based on temp target of 120; Adjusting basal from 1.65 to 1.35; ISF from 58.9 to 73.6
|
||||||
|
//sensitivityRatio = 2/(2+(target_bg-normalTarget)/40);
|
||||||
|
var c = halfBasalTarget - normalTarget;
|
||||||
|
sensitivityRatio = c/(c+target_bg-normalTarget);
|
||||||
|
// limit sensitivityRatio to profile.autosens_max (1.2x by default)
|
||||||
|
sensitivityRatio = Math.min(sensitivityRatio, profile.autosens_max);
|
||||||
|
sensitivityRatio = round(sensitivityRatio,2);
|
||||||
|
console.log("Sensitivity ratio set to "+sensitivityRatio+" based on temp target of "+target_bg+"; ");
|
||||||
|
sens = sens / sensitivityRatio ;
|
||||||
|
sens = round(sens, 1);
|
||||||
|
console.log("ISF from "+variable_sens+" to "+sens+ "due to temp target; ");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sensitivityRatio = ( tdd_24 / tdd7 );
|
||||||
|
}
|
||||||
|
if (sensitivityRatio > 1) {
|
||||||
|
sensitivityRatio = Math.min(sensitivityRatio, profile.autosens_max);
|
||||||
|
sensitivityRatio = round(sensitivityRatio,2);
|
||||||
|
console.log("Sensitivity ratio: "+sensitivityRatio+"; ");
|
||||||
|
}
|
||||||
|
else if( sensitivityRatio < 1) {
|
||||||
|
sensitivityRatio = Math.max(sensitivityRatio, profile.autosens_min);
|
||||||
|
sensitivityRatio = round(sensitivityRatio,2);
|
||||||
|
console.log("Sensitivity ratio: "+sensitivityRatio+"; ");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("Sensitivity ratio: "+sensitivityRatio+"; ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (sensitivityRatio && profile.openapsama_useautosens === true) {
|
||||||
|
basal = profile.current_basal * sensitivityRatio;
|
||||||
|
basal = round_basal(basal, profile);
|
||||||
|
if (basal !== profile_current_basal) {
|
||||||
|
console.log("Adjusting basal from "+profile_current_basal+" to "+basal+"; ");
|
||||||
|
} else {
|
||||||
|
console.log("Autosens disabled. Basal unchanged: "+basal+"; ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (meal_data.TDDPUMP){
|
// adjust min, max, and target BG for sensitivity, such that 50% increase in ISF raises target from 100 to 120
|
||||||
var tdd_pump = ( (meal_data.TDDPUMP / now ) * 24);
|
if (profile.temptargetSet) {
|
||||||
|
//console.log("Temp Target set, not adjusting with autosens; ");
|
||||||
|
} else {
|
||||||
|
if ( profile.sensitivity_raises_target && sensitivityRatio < 1 && profile.openapsama_useautosens === true || profile.resistance_lowers_target && sensitivityRatio > 1 && profile.openapsama_useautosens === true) {
|
||||||
|
// with a target of 100, default 0.7-1.2 autosens min/max range would allow a 93-117 target range
|
||||||
|
min_bg = round((min_bg - 60) / sensitivityRatio) + 60;
|
||||||
|
max_bg = round((max_bg - 60) / sensitivityRatio) + 60;
|
||||||
|
var new_target_bg = round((target_bg - 60) / sensitivityRatio) + 60;
|
||||||
|
// don't allow target_bg below 80
|
||||||
|
new_target_bg = Math.max(80, new_target_bg);
|
||||||
|
if (target_bg === new_target_bg) {
|
||||||
|
console.log("target_bg unchanged: "+new_target_bg+"; ");
|
||||||
|
} else {
|
||||||
|
console.log("target_bg from "+target_bg+" to "+new_target_bg+"; ");
|
||||||
|
}
|
||||||
|
target_bg = new_target_bg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
var tdd_pump = (( basal * 24 ) * 2.8);
|
|
||||||
|
if (typeof iob_data === 'undefined' ) {
|
||||||
|
rT.error ='Error: iob_data undefined. ';
|
||||||
|
return rT;
|
||||||
}
|
}
|
||||||
var TDD = (tdd7 * 0.4) + (tdd_pump * 0.6);
|
|
||||||
|
|
||||||
console.error("Pump extrapolated TDD = "+tdd_pump+"; ");
|
var iobArray = iob_data;
|
||||||
//if (tdd7 > 0){
|
if (typeof(iob_data.length) && iob_data.length > 1) {
|
||||||
if ( tdd_pump > tdd7 && now < 5 || now < 7 && TDD < ( 0.8 * tdd7 ) ){
|
iob_data = iobArray[0];
|
||||||
TDD = ( 0.8 * tdd7 );
|
//console.error(JSON.stringify(iob_data[0]));
|
||||||
console.log("Excess or too low insulin from pump so TDD set to "+TDD+" based on 75% of TDD7; ");
|
}
|
||||||
rT.reason += "TDD: " +TDD+ " due to low or high tdd from pump; ";
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (tdd_pump > (1.75 * tdd7)){
|
if (typeof iob_data.activity === 'undefined' || typeof iob_data.iob === 'undefined' ) {
|
||||||
TDD = tdd7;
|
rT.error ='Error: iob_data missing some property. ';
|
||||||
console.error("TDD set to TDD7 due to high pump usage reported. TDD = "+TDD+"; ");
|
return rT;
|
||||||
rT.reason += "TDD set to TDD7 due to high pump usage reported. TDD = "+TDD+"; ";
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
var tick;
|
||||||
|
|
||||||
else if (tdd_pump < (0.33 * tdd7)){
|
if (glucose_status.delta > -0.5) {
|
||||||
TDD = (tdd7 * 0.25) + (tdd_pump * 0.75);
|
tick = "+" + round(glucose_status.delta,0);
|
||||||
console.error("TDD weighted to pump due to low insulin usage. TDD = "+TDD+"; ");
|
} else {
|
||||||
rT.reason += "TDD weighted to pump due to low insulin usage. TDD = "+TDD+"; ";
|
tick = round(glucose_status.delta,0);
|
||||||
}
|
}
|
||||||
|
//var minDelta = Math.min(glucose_status.delta, glucose_status.short_avgdelta, glucose_status.long_avgdelta);
|
||||||
|
var minDelta = Math.min(glucose_status.delta, glucose_status.short_avgdelta);
|
||||||
|
var minAvgDelta = Math.min(glucose_status.short_avgdelta, glucose_status.long_avgdelta);
|
||||||
|
var maxDelta = Math.max(glucose_status.delta, glucose_status.short_avgdelta, glucose_status.long_avgdelta);
|
||||||
|
|
||||||
else {
|
|
||||||
console.log("TDD = " +TDD+ " based on standard pump 60/tdd7 40 split; ");
|
|
||||||
rT.reason += "TDD: " +TDD+ " based on standard pump 60/tdd7 40 split; ";
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error(" ");
|
|
||||||
|
|
||||||
|
|
||||||
var variable_sens = (277700 / (TDD * bg));
|
|
||||||
variable_sens = round(variable_sens,1);
|
|
||||||
console.log("Current sensitivity for predictions is " +variable_sens+" based on current bg");
|
|
||||||
console.error(" ");
|
|
||||||
|
|
||||||
sens = variable_sens;
|
|
||||||
if ( high_temptarget_raises_sensitivity && profile.temptargetSet && target_bg > normalTarget || profile.low_temptarget_lowers_sensitivity && profile.temptargetSet && target_bg < normalTarget ) {
|
|
||||||
sens = sens / sensitivityRatio ;
|
|
||||||
sens = round(sens, 1);
|
|
||||||
console.log("ISF from "+variable_sens+" to "+sens+ "due to temp target; ");
|
|
||||||
} else {
|
|
||||||
sens = sens;
|
|
||||||
sens = round(sens, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.error("; CR:",profile.carb_ratio);
|
console.error("; CR:",profile.carb_ratio);
|
||||||
|
|
||||||
|
@ -772,19 +805,27 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_
|
||||||
|
|
||||||
console.error("UAM Impact:",uci,"mg/dL per 5m; UAM Duration:",UAMduration,"hours");
|
console.error("UAM Impact:",uci,"mg/dL per 5m; UAM Duration:",UAMduration,"hours");
|
||||||
|
|
||||||
console.log("EventualBG is" +eventualBG+" ;");
|
console.log("EventualBG is" +eventualBG+" ;");
|
||||||
|
|
||||||
|
if (bg > target_bg && glucose_status.delta < 3 && glucose_status.delta > -3 && glucose_status.short_avgdelta > -3 && glucose_status.short_avgdelta < 3 && eventualBG > target_bg && eventualBG < bg ) {
|
||||||
|
var future_sens = ( 277700 / (TDD * ((eventualBG * 0.5) + (bg * 0.5) ) ) );
|
||||||
|
console.log("Future state sensitivity is " +future_sens+" based on eventual and current bg due to flat glucose level above target");
|
||||||
|
rT.reason += "Dosing sensitivity: " +future_sens+" using eventual BG;";
|
||||||
|
}
|
||||||
|
|
||||||
|
else if( glucose_status.delta > 0 && eventualBG > target_bg ) {
|
||||||
|
var future_sens = ( 277700 / (TDD * bg) );
|
||||||
|
console.log("Future state sensitivity is " +future_sens+" using current bg due to small delta or variation");
|
||||||
|
rT.reason += "Dosing sensitivity: " +future_sens+" using current BG;";
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
var future_sens = ( 277700 / (TDD * eventualBG) );
|
||||||
|
console.log("Future state sensitivity is " +future_sens+" based on eventual bg due to -ve delta");
|
||||||
|
rT.reason += "Dosing sensitivity: " +future_sens+" using eventual BG;";
|
||||||
|
}
|
||||||
|
var future_sens = round(future_sens,1);
|
||||||
|
|
||||||
if( glucose_status.delta >= 0 || bg > 60 && glucose_status.delta < 2 && glucose_status.delta > -2 && glucose_status.short_avgdelta > -2 && glucose_status.short_avgdelta < 2 || eventualBG > target_bg && glucose_status.delta < 0 ) {
|
|
||||||
var future_sens = ( 277700 / (TDD * bg) );
|
|
||||||
console.log("Future state sensitivity is " +future_sens+" using current bg due to no COB & small delta or variation");
|
|
||||||
rT.reason += "Dosing sensitivity: " +future_sens+" using current BG;";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var future_sens = ( 277700 / (TDD * eventualBG));
|
|
||||||
console.log("Future state sensitivity is " +future_sens+" based on eventual bg due to -ve delta");
|
|
||||||
rT.reason += "Dosing sensitivity: " +future_sens+" using eventual BG;";
|
|
||||||
}
|
|
||||||
var future_sens = round(future_sens,1);
|
|
||||||
|
|
||||||
|
|
||||||
minIOBPredBG = Math.max(39,minIOBPredBG);
|
minIOBPredBG = Math.max(39,minIOBPredBG);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import android.os.Bundle
|
||||||
import android.os.PersistableBundle
|
import android.os.PersistableBundle
|
||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
import android.text.method.LinkMovementMethod
|
import android.text.method.LinkMovementMethod
|
||||||
|
import android.text.style.ForegroundColorSpan
|
||||||
import android.text.util.Linkify
|
import android.text.util.Linkify
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
|
@ -19,10 +20,10 @@ import android.widget.EditText
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.core.view.GravityCompat
|
import androidx.core.view.GravityCompat
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import com.joanzapata.iconify.Iconify
|
import com.joanzapata.iconify.Iconify
|
||||||
|
@ -33,6 +34,7 @@ import info.nightscout.androidaps.database.entities.UserEntry.Action
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
||||||
import info.nightscout.androidaps.databinding.ActivityMainBinding
|
import info.nightscout.androidaps.databinding.ActivityMainBinding
|
||||||
import info.nightscout.androidaps.events.EventAppExit
|
import info.nightscout.androidaps.events.EventAppExit
|
||||||
|
import info.nightscout.androidaps.events.EventInitializationChanged
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||||
import info.nightscout.androidaps.events.EventRebuildTabs
|
import info.nightscout.androidaps.events.EventRebuildTabs
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
|
@ -50,6 +52,7 @@ 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.isRunningRealPumpTest
|
import info.nightscout.androidaps.utils.extensions.isRunningRealPumpTest
|
||||||
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
||||||
|
import info.nightscout.androidaps.utils.protection.PasswordCheck
|
||||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.androidaps.utils.tabs.TabPageAdapter
|
import info.nightscout.androidaps.utils.tabs.TabPageAdapter
|
||||||
|
@ -67,7 +70,6 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||||
@Inject lateinit var rxBus: RxBus
|
|
||||||
@Inject lateinit var androidPermission: AndroidPermission
|
@Inject lateinit var androidPermission: AndroidPermission
|
||||||
@Inject lateinit var sp: SP
|
@Inject lateinit var sp: SP
|
||||||
@Inject lateinit var versionCheckerUtils: VersionCheckerUtils
|
@Inject lateinit var versionCheckerUtils: VersionCheckerUtils
|
||||||
|
@ -84,12 +86,13 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
@Inject lateinit var config: Config
|
@Inject lateinit var config: Config
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
@Inject lateinit var profileFunction: ProfileFunction
|
@Inject lateinit var profileFunction: ProfileFunction
|
||||||
|
@Inject lateinit var passwordCheck: PasswordCheck
|
||||||
|
|
||||||
private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
|
private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
|
||||||
private var pluginPreferencesMenuItem: MenuItem? = null
|
private var pluginPreferencesMenuItem: MenuItem? = null
|
||||||
private var menu: Menu? = null
|
private var menu: Menu? = null
|
||||||
private var menuOpen = false
|
private var menuOpen = false
|
||||||
|
private var isProtectionCheckActive = false
|
||||||
private lateinit var binding: ActivityMainBinding
|
private lateinit var binding: ActivityMainBinding
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -115,6 +118,7 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
override fun onPageSelected(position: Int) {
|
override fun onPageSelected(position: Int) {
|
||||||
setPluginPreferenceMenuName()
|
setPluginPreferenceMenuName()
|
||||||
checkPluginPreferences(binding.mainPager)
|
checkPluginPreferences(binding.mainPager)
|
||||||
|
setDisabledMenuItemColorPluginPreferences()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -134,6 +138,12 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
.toObservable(EventPreferenceChange::class.java)
|
.toObservable(EventPreferenceChange::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({ processPreferenceChange(it) }, fabricPrivacy::logException)
|
.subscribe({ processPreferenceChange(it) }, fabricPrivacy::logException)
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventInitializationChanged::class.java)
|
||||||
|
.observeOn(aapsSchedulers.main)
|
||||||
|
.subscribe({
|
||||||
|
passwordCheck.passwordResetCheck(this)
|
||||||
|
}, fabricPrivacy::logException)
|
||||||
if (startWizard() && !isRunningRealPumpTest()) {
|
if (startWizard() && !isRunningRealPumpTest()) {
|
||||||
protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, {
|
protectionCheck.queryProtection(this, ProtectionCheck.Protection.PREFERENCES, {
|
||||||
startActivity(Intent(this, SetupWizardActivity::class.java))
|
startActivity(Intent(this, SetupWizardActivity::class.java))
|
||||||
|
@ -168,10 +178,13 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
protectionCheck.queryProtection(this, ProtectionCheck.Protection.APPLICATION, null,
|
if (!isProtectionCheckActive) {
|
||||||
UIRunnable { OKDialog.show(this, "", rh.gs(R.string.authorizationfailed)) { finish() } },
|
isProtectionCheckActive = true
|
||||||
UIRunnable { OKDialog.show(this, "", rh.gs(R.string.authorizationfailed)) { finish() } }
|
protectionCheck.queryProtection(this, ProtectionCheck.Protection.APPLICATION, UIRunnable { isProtectionCheckActive = false },
|
||||||
)
|
UIRunnable { OKDialog.show(this, "", rh.gs(R.string.authorizationfailed)) { isProtectionCheckActive = false; finish() } },
|
||||||
|
UIRunnable { OKDialog.show(this, "", rh.gs(R.string.authorizationfailed)) { isProtectionCheckActive = false; finish() } }
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setWakeLock() {
|
private fun setWakeLock() {
|
||||||
|
@ -252,6 +265,14 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
return super.dispatchTouchEvent(event)
|
return super.dispatchTouchEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setDisabledMenuItemColorPluginPreferences() {
|
||||||
|
if (pluginPreferencesMenuItem?.isEnabled == false) {
|
||||||
|
val spanString = SpannableString(this.menu?.findItem(R.id.nav_plugin_preferences)?.title.toString())
|
||||||
|
spanString.setSpan(ForegroundColorSpan(rh.gac(R.attr.disabledTextColor)), 0, spanString.length, 0)
|
||||||
|
this.menu?.findItem(R.id.nav_plugin_preferences)?.title = spanString
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun setPluginPreferenceMenuName() {
|
private fun setPluginPreferenceMenuName() {
|
||||||
if (binding.mainPager.currentItem >= 0) {
|
if (binding.mainPager.currentItem >= 0) {
|
||||||
val plugin = (binding.mainPager.adapter as TabPageAdapter).getPluginAt(binding.mainPager.currentItem)
|
val plugin = (binding.mainPager.adapter as TabPageAdapter).getPluginAt(binding.mainPager.currentItem)
|
||||||
|
@ -270,7 +291,7 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPanelClosed(featureId: Int, menu: Menu) {
|
override fun onPanelClosed(featureId: Int, menu: Menu) {
|
||||||
menuOpen = false;
|
menuOpen = false
|
||||||
super.onPanelClosed(featureId, menu)
|
super.onPanelClosed(featureId, menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,6 +301,7 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
pluginPreferencesMenuItem = menu.findItem(R.id.nav_plugin_preferences)
|
pluginPreferencesMenuItem = menu.findItem(R.id.nav_plugin_preferences)
|
||||||
setPluginPreferenceMenuName()
|
setPluginPreferenceMenuName()
|
||||||
checkPluginPreferences(binding.mainPager)
|
checkPluginPreferences(binding.mainPager)
|
||||||
|
setDisabledMenuItemColorPluginPreferences()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +342,7 @@ class MainActivity : NoSplashAppCompatActivity() {
|
||||||
message += rh.gs(R.string.about_link_urls)
|
message += rh.gs(R.string.about_link_urls)
|
||||||
val messageSpanned = SpannableString(message)
|
val messageSpanned = SpannableString(message)
|
||||||
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS)
|
Linkify.addLinks(messageSpanned, Linkify.WEB_URLS)
|
||||||
AlertDialog.Builder(this, R.style.DialogTheme)
|
MaterialAlertDialogBuilder(this, R.style.DialogTheme)
|
||||||
.setTitle(rh.gs(R.string.app_name) + " " + BuildConfig.VERSION)
|
.setTitle(rh.gs(R.string.app_name) + " " + BuildConfig.VERSION)
|
||||||
.setIcon(iconsProvider.getIcon())
|
.setIcon(iconsProvider.getIcon())
|
||||||
.setMessage(messageSpanned)
|
.setMessage(messageSpanned)
|
||||||
|
|
|
@ -6,6 +6,13 @@ import android.content.IntentFilter
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import android.net.wifi.WifiManager
|
import android.net.wifi.WifiManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.HandlerThread
|
||||||
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
|
import androidx.work.Data
|
||||||
|
import androidx.work.ExistingPeriodicWorkPolicy
|
||||||
|
import androidx.work.PeriodicWorkRequest
|
||||||
|
import androidx.work.WorkManager
|
||||||
import com.uber.rxdogtag.RxDogTag
|
import com.uber.rxdogtag.RxDogTag
|
||||||
import dagger.android.AndroidInjector
|
import dagger.android.AndroidInjector
|
||||||
import dagger.android.DaggerApplication
|
import dagger.android.DaggerApplication
|
||||||
|
@ -20,24 +27,23 @@ import info.nightscout.androidaps.di.StaticInjector
|
||||||
import info.nightscout.androidaps.interfaces.Config
|
import info.nightscout.androidaps.interfaces.Config
|
||||||
import info.nightscout.androidaps.interfaces.ConfigBuilder
|
import info.nightscout.androidaps.interfaces.ConfigBuilder
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase
|
import info.nightscout.androidaps.interfaces.PluginBase
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
import info.nightscout.androidaps.plugins.configBuilder.PluginStore
|
||||||
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
|
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtils
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
|
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
|
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
|
||||||
import info.nightscout.androidaps.receivers.BTReceiver
|
import info.nightscout.androidaps.plugins.general.themes.ThemeSwitcherPlugin
|
||||||
import info.nightscout.androidaps.receivers.ChargingStateReceiver
|
import info.nightscout.androidaps.receivers.*
|
||||||
import info.nightscout.androidaps.receivers.KeepAliveReceiver.KeepAliveManager
|
|
||||||
import info.nightscout.androidaps.receivers.NetworkChangeReceiver
|
|
||||||
import info.nightscout.androidaps.receivers.TimeDateOrTZChangeReceiver
|
|
||||||
import info.nightscout.androidaps.services.AlarmSoundServiceHelper
|
import info.nightscout.androidaps.services.AlarmSoundServiceHelper
|
||||||
import info.nightscout.androidaps.utils.ActivityMonitor
|
import info.nightscout.androidaps.utils.ActivityMonitor
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
import info.nightscout.androidaps.utils.LocalAlertUtils
|
||||||
|
import info.nightscout.androidaps.utils.ProcessLifecycleListener
|
||||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
import info.nightscout.androidaps.utils.locale.LocaleHelper
|
||||||
import info.nightscout.androidaps.utils.protection.PasswordCheck
|
import info.nightscout.androidaps.widget.updateWidget
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.exceptions.UndeliverableException
|
import io.reactivex.rxjava3.exceptions.UndeliverableException
|
||||||
|
@ -46,6 +52,7 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins
|
||||||
import net.danlew.android.joda.JodaTimeAndroid
|
import net.danlew.android.joda.JodaTimeAndroid
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.SocketException
|
import java.net.SocketException
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class MainApp : DaggerApplication() {
|
class MainApp : DaggerApplication() {
|
||||||
|
@ -60,16 +67,20 @@ class MainApp : DaggerApplication() {
|
||||||
@Inject lateinit var config: Config
|
@Inject lateinit var config: Config
|
||||||
@Inject lateinit var buildHelper: BuildHelper
|
@Inject lateinit var buildHelper: BuildHelper
|
||||||
@Inject lateinit var configBuilder: ConfigBuilder
|
@Inject lateinit var configBuilder: ConfigBuilder
|
||||||
@Inject lateinit var keepAliveManager: KeepAliveManager
|
|
||||||
@Inject lateinit var plugins: List<@JvmSuppressWildcards PluginBase>
|
@Inject lateinit var plugins: List<@JvmSuppressWildcards PluginBase>
|
||||||
@Inject lateinit var compatDBHelper: CompatDBHelper
|
@Inject lateinit var compatDBHelper: CompatDBHelper
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
@Inject lateinit var staticInjector: StaticInjector// TODO avoid , here fake only to initialize
|
@Inject lateinit var staticInjector: StaticInjector// TODO avoid , here fake only to initialize
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
@Inject lateinit var passwordCheck: PasswordCheck
|
|
||||||
@Inject lateinit var alarmSoundServiceHelper: AlarmSoundServiceHelper
|
@Inject lateinit var alarmSoundServiceHelper: AlarmSoundServiceHelper
|
||||||
@Inject lateinit var notificationStore: NotificationStore
|
@Inject lateinit var notificationStore: NotificationStore
|
||||||
|
@Inject lateinit var processLifecycleListener: ProcessLifecycleListener
|
||||||
|
@Inject lateinit var profileSwitchPlugin: ThemeSwitcherPlugin
|
||||||
|
@Inject lateinit var localAlertUtils: LocalAlertUtils
|
||||||
|
|
||||||
|
private var handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
|
||||||
|
private lateinit var refreshWidget: Runnable
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
@ -77,6 +88,7 @@ class MainApp : DaggerApplication() {
|
||||||
RxDogTag.install()
|
RxDogTag.install()
|
||||||
setRxErrorHandler()
|
setRxErrorHandler()
|
||||||
LocaleHelper.update(this)
|
LocaleHelper.update(this)
|
||||||
|
ProcessLifecycleOwner.get().lifecycle.addObserver(processLifecycleListener)
|
||||||
|
|
||||||
var gitRemote: String? = BuildConfig.REMOTE
|
var gitRemote: String? = BuildConfig.REMOTE
|
||||||
var commitHash: String? = BuildConfig.HEAD
|
var commitHash: String? = BuildConfig.HEAD
|
||||||
|
@ -84,21 +96,10 @@ class MainApp : DaggerApplication() {
|
||||||
gitRemote = null
|
gitRemote = null
|
||||||
commitHash = null
|
commitHash = null
|
||||||
}
|
}
|
||||||
disposable += repository.runTransaction(VersionChangeTransaction(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, gitRemote, commitHash)).subscribe()
|
|
||||||
if (sp.getBoolean(R.string.key_ns_logappstartedevent, config.APS))
|
|
||||||
disposable += repository
|
|
||||||
.runTransaction(
|
|
||||||
InsertIfNewByTimestampTherapyEventTransaction(
|
|
||||||
timestamp = dateUtil.now(),
|
|
||||||
type = TherapyEvent.Type.NOTE,
|
|
||||||
note = getString(info.nightscout.androidaps.core.R.string.androidaps_start) + " - " + Build.MANUFACTURER + " " + Build.MODEL,
|
|
||||||
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.subscribe()
|
|
||||||
disposable += compatDBHelper.dbChangeDisposable()
|
disposable += compatDBHelper.dbChangeDisposable()
|
||||||
registerActivityLifecycleCallbacks(activityMonitor)
|
registerActivityLifecycleCallbacks(activityMonitor)
|
||||||
JodaTimeAndroid.init(this)
|
JodaTimeAndroid.init(this)
|
||||||
|
profileSwitchPlugin.setThemeMode()
|
||||||
aapsLogger.debug("Version: " + BuildConfig.VERSION_NAME)
|
aapsLogger.debug("Version: " + BuildConfig.VERSION_NAME)
|
||||||
aapsLogger.debug("BuildVersion: " + BuildConfig.BUILDVERSION)
|
aapsLogger.debug("BuildVersion: " + BuildConfig.BUILDVERSION)
|
||||||
aapsLogger.debug("Remote: " + BuildConfig.REMOTE)
|
aapsLogger.debug("Remote: " + BuildConfig.REMOTE)
|
||||||
|
@ -113,10 +114,38 @@ class MainApp : DaggerApplication() {
|
||||||
// Register all tabs in app here
|
// Register all tabs in app here
|
||||||
pluginStore.plugins = plugins
|
pluginStore.plugins = plugins
|
||||||
configBuilder.initialize()
|
configBuilder.initialize()
|
||||||
keepAliveManager.setAlarm(this)
|
|
||||||
|
disposable += repository.runTransaction(VersionChangeTransaction(BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE, gitRemote, commitHash)).subscribe()
|
||||||
|
if (sp.getBoolean(R.string.key_ns_logappstartedevent, config.APS))
|
||||||
|
disposable += repository
|
||||||
|
.runTransaction(
|
||||||
|
InsertIfNewByTimestampTherapyEventTransaction(
|
||||||
|
timestamp = dateUtil.now(),
|
||||||
|
type = TherapyEvent.Type.NOTE,
|
||||||
|
note = getString(info.nightscout.androidaps.core.R.string.androidaps_start) + " - " + Build.MANUFACTURER + " " + Build.MODEL,
|
||||||
|
glucoseUnit = TherapyEvent.GlucoseUnit.MGDL
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.subscribe()
|
||||||
|
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
|
||||||
|
"KeepAlive",
|
||||||
|
ExistingPeriodicWorkPolicy.REPLACE,
|
||||||
|
PeriodicWorkRequest.Builder(KeepAliveWorker::class.java, 15, TimeUnit.MINUTES)
|
||||||
|
.setInputData(Data.Builder().putString("schedule", "KeepAlive").build())
|
||||||
|
.setInitialDelay(5, TimeUnit.SECONDS)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
localAlertUtils.shortenSnoozeInterval()
|
||||||
|
localAlertUtils.preSnoozeAlarms()
|
||||||
doMigrations()
|
doMigrations()
|
||||||
uel.log(UserEntry.Action.START_AAPS, UserEntry.Sources.Aaps)
|
uel.log(UserEntry.Action.START_AAPS, UserEntry.Sources.Aaps)
|
||||||
passwordCheck.passwordResetCheck(this)
|
|
||||||
|
// schedule widget update
|
||||||
|
refreshWidget = Runnable {
|
||||||
|
handler.postDelayed(refreshWidget, 60000)
|
||||||
|
updateWidget(this)
|
||||||
|
}
|
||||||
|
handler.postDelayed(refreshWidget, 60000)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setRxErrorHandler() {
|
private fun setRxErrorHandler() {
|
||||||
|
@ -186,7 +215,6 @@ class MainApp : DaggerApplication() {
|
||||||
override fun onTerminate() {
|
override fun onTerminate() {
|
||||||
aapsLogger.debug(LTag.CORE, "onTerminate")
|
aapsLogger.debug(LTag.CORE, "onTerminate")
|
||||||
unregisterActivityLifecycleCallbacks(activityMonitor)
|
unregisterActivityLifecycleCallbacks(activityMonitor)
|
||||||
keepAliveManager.cancelAlarm(this)
|
|
||||||
alarmSoundServiceHelper.stopService(this)
|
alarmSoundServiceHelper.stopService(this)
|
||||||
super.onTerminate()
|
super.onTerminate()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ package info.nightscout.androidaps.activities
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.DatePickerDialog
|
import android.app.DatePickerDialog
|
||||||
import android.graphics.Color
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -18,21 +18,19 @@ import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
||||||
import info.nightscout.androidaps.events.EventCustomCalculationFinished
|
import info.nightscout.androidaps.events.EventCustomCalculationFinished
|
||||||
import info.nightscout.androidaps.events.EventRefreshOverview
|
import info.nightscout.androidaps.events.EventRefreshOverview
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
|
import info.nightscout.androidaps.extensions.toVisibilityKeepSpace
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
import info.nightscout.androidaps.interfaces.Config
|
import info.nightscout.androidaps.interfaces.Config
|
||||||
import info.nightscout.androidaps.interfaces.Loop
|
import info.nightscout.androidaps.interfaces.Loop
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
|
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
|
||||||
import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
||||||
import info.nightscout.androidaps.plugins.general.overview.OverviewMenus
|
import info.nightscout.androidaps.plugins.general.overview.OverviewMenus
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.events.EventUpdateOverviewGraph
|
||||||
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
|
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventBucketedDataCreated
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
|
import info.nightscout.androidaps.receivers.DataWorker
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.DefaultValueHelper
|
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
|
@ -40,6 +38,7 @@ import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.utils.Translator
|
import info.nightscout.androidaps.utils.Translator
|
||||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.androidaps.workflow.CalculationWorkflow
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
@ -52,15 +51,11 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
@Inject lateinit var injector: HasAndroidInjector
|
@Inject lateinit var injector: HasAndroidInjector
|
||||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||||
@Inject lateinit var rxBus: RxBus
|
|
||||||
@Inject lateinit var sp: SP
|
@Inject lateinit var sp: SP
|
||||||
@Inject lateinit var profileFunction: ProfileFunction
|
@Inject lateinit var profileFunction: ProfileFunction
|
||||||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||||
@Inject lateinit var activePlugin: ActivePlugin
|
@Inject lateinit var activePlugin: ActivePlugin
|
||||||
@Inject lateinit var buildHelper: BuildHelper
|
@Inject lateinit var buildHelper: BuildHelper
|
||||||
@Inject lateinit var sensitivityOref1Plugin: SensitivityOref1Plugin
|
|
||||||
@Inject lateinit var sensitivityAAPSPlugin: SensitivityAAPSPlugin
|
|
||||||
@Inject lateinit var sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin
|
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||||
@Inject lateinit var overviewMenus: OverviewMenus
|
@Inject lateinit var overviewMenus: OverviewMenus
|
||||||
|
@ -69,6 +64,9 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
@Inject lateinit var loop: Loop
|
@Inject lateinit var loop: Loop
|
||||||
@Inject lateinit var nsDeviceStatus: NSDeviceStatus
|
@Inject lateinit var nsDeviceStatus: NSDeviceStatus
|
||||||
@Inject lateinit var translator: Translator
|
@Inject lateinit var translator: Translator
|
||||||
|
@Inject lateinit var context: Context
|
||||||
|
@Inject lateinit var dataWorker: DataWorker
|
||||||
|
@Inject lateinit var calculationWorkflow: CalculationWorkflow
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
|
@ -91,6 +89,17 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
// We don't want to use injected singletons but own instance working on top of different data
|
// We don't want to use injected singletons but own instance working on top of different data
|
||||||
|
overviewData =
|
||||||
|
OverviewData(
|
||||||
|
aapsLogger,
|
||||||
|
rh,
|
||||||
|
dateUtil,
|
||||||
|
sp,
|
||||||
|
activePlugin,
|
||||||
|
defaultValueHelper,
|
||||||
|
profileFunction,
|
||||||
|
repository
|
||||||
|
)
|
||||||
iobCobCalculator =
|
iobCobCalculator =
|
||||||
IobCobCalculatorPlugin(
|
IobCobCalculatorPlugin(
|
||||||
injector,
|
injector,
|
||||||
|
@ -101,30 +110,11 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
rh,
|
rh,
|
||||||
profileFunction,
|
profileFunction,
|
||||||
activePlugin,
|
activePlugin,
|
||||||
sensitivityOref1Plugin,
|
|
||||||
sensitivityAAPSPlugin,
|
|
||||||
sensitivityWeightedAveragePlugin,
|
|
||||||
fabricPrivacy,
|
fabricPrivacy,
|
||||||
dateUtil,
|
dateUtil,
|
||||||
repository
|
|
||||||
)
|
|
||||||
overviewData =
|
|
||||||
OverviewData(
|
|
||||||
injector,
|
|
||||||
aapsLogger,
|
|
||||||
rh,
|
|
||||||
dateUtil,
|
|
||||||
sp,
|
|
||||||
activePlugin,
|
|
||||||
defaultValueHelper,
|
|
||||||
profileFunction,
|
|
||||||
config,
|
|
||||||
loop,
|
|
||||||
nsDeviceStatus,
|
|
||||||
repository,
|
repository,
|
||||||
overviewMenus,
|
overviewData,
|
||||||
iobCobCalculator,
|
calculationWorkflow
|
||||||
translator
|
|
||||||
)
|
)
|
||||||
|
|
||||||
binding.left.setOnClickListener {
|
binding.left.setOnClickListener {
|
||||||
|
@ -179,7 +169,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
val cal = Calendar.getInstance()
|
val cal = Calendar.getInstance()
|
||||||
cal.timeInMillis = overviewData.fromTime
|
cal.timeInMillis = overviewData.fromTime
|
||||||
DatePickerDialog(
|
DatePickerDialog(
|
||||||
this, R.style.MaterialPickerTheme,
|
this,
|
||||||
dateSetListener,
|
dateSetListener,
|
||||||
cal.get(Calendar.YEAR),
|
cal.get(Calendar.YEAR),
|
||||||
cal.get(Calendar.MONTH),
|
cal.get(Calendar.MONTH),
|
||||||
|
@ -188,18 +178,19 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val dm = DisplayMetrics()
|
val dm = DisplayMetrics()
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R)
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R)
|
||||||
display?.getRealMetrics(dm)
|
display?.getRealMetrics(dm)
|
||||||
else
|
else
|
||||||
@Suppress("DEPRECATION") windowManager.defaultDisplay.getMetrics(dm)
|
windowManager.defaultDisplay.getMetrics(dm)
|
||||||
|
|
||||||
|
|
||||||
axisWidth = if (dm.densityDpi <= 120) 3 else if (dm.densityDpi <= 160) 10 else if (dm.densityDpi <= 320) 35 else if (dm.densityDpi <= 420) 50 else if (dm.densityDpi <= 560) 70 else 80
|
axisWidth = if (dm.densityDpi <= 120) 3 else if (dm.densityDpi <= 160) 10 else if (dm.densityDpi <= 320) 35 else if (dm.densityDpi <= 420) 50 else if (dm.densityDpi <= 560) 70 else 80
|
||||||
binding.bgGraph.gridLabelRenderer?.gridColor = rh.gc(R.color.graphgrid)
|
binding.bgGraph.gridLabelRenderer?.gridColor = rh.gac(this, R.attr.graphgrid)
|
||||||
binding.bgGraph.gridLabelRenderer?.reloadStyles()
|
binding.bgGraph.gridLabelRenderer?.reloadStyles()
|
||||||
binding.bgGraph.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
binding.bgGraph.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
||||||
|
|
||||||
overviewMenus.setupChartMenu(binding.chartMenuButton)
|
overviewMenus.setupChartMenu(context, binding.chartMenuButton)
|
||||||
prepareGraphsIfNeeded(overviewMenus.setting.size)
|
prepareGraphsIfNeeded(overviewMenus.setting.size)
|
||||||
savedInstanceState?.let { bundle ->
|
savedInstanceState?.let { bundle ->
|
||||||
rangeToDisplay = bundle.getInt("rangeToDisplay", 0)
|
rangeToDisplay = bundle.getInt("rangeToDisplay", 0)
|
||||||
|
@ -211,7 +202,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
iobCobCalculator.stopCalculation("onPause")
|
calculationWorkflow.stopCalculation(CalculationWorkflow.HISTORY_CALCULATION, "onPause")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
@ -233,22 +224,11 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventIobCalculationProgress::class.java)
|
.toObservable(EventIobCalculationProgress::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({
|
.subscribe({ updateCalcProgress(it.pass.finalPercent(it.progressPct)) }, fabricPrivacy::logException)
|
||||||
if (it.cause is EventCustomCalculationFinished)
|
|
||||||
binding.overviewIobcalculationprogess.text = it.progress
|
|
||||||
}, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventRefreshOverview::class.java)
|
.toObservable(EventUpdateOverviewGraph::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({ updateGUI("EventRefreshOverview") }, fabricPrivacy::logException)
|
.subscribe({ updateGUI("EventRefreshOverview") }, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventBucketedDataCreated::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({
|
|
||||||
overviewData.prepareBucketedData("EventBucketedDataCreated")
|
|
||||||
overviewData.prepareBgData("EventBucketedDataCreated")
|
|
||||||
rxBus.send(EventRefreshOverview("EventBucketedDataCreated"))
|
|
||||||
}, fabricPrivacy::logException)
|
|
||||||
|
|
||||||
if (overviewData.fromTime == 0L) {
|
if (overviewData.fromTime == 0L) {
|
||||||
// set start of current day
|
// set start of current day
|
||||||
|
@ -279,12 +259,12 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
val graph = GraphView(this)
|
val graph = GraphView(this)
|
||||||
graph.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, rh.dpToPx(100)).also { it.setMargins(0, rh.dpToPx(15), 0, rh.dpToPx(10)) }
|
graph.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, rh.dpToPx(100)).also { it.setMargins(0, rh.dpToPx(15), 0, rh.dpToPx(10)) }
|
||||||
graph.gridLabelRenderer?.gridColor = rh.gc(R.color.graphgrid)
|
graph.gridLabelRenderer?.gridColor = rh.gac(R.attr.graphgrid)
|
||||||
graph.gridLabelRenderer?.reloadStyles()
|
graph.gridLabelRenderer?.reloadStyles()
|
||||||
graph.gridLabelRenderer?.isHorizontalLabelsVisible = false
|
graph.gridLabelRenderer?.isHorizontalLabelsVisible = false
|
||||||
graph.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
graph.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
||||||
graph.gridLabelRenderer?.numVerticalLabels = 3
|
graph.gridLabelRenderer?.numVerticalLabels = 3
|
||||||
graph.viewport.backgroundColor = Color.argb(20, 255, 255, 255) // 8% of gray
|
graph.viewport.backgroundColor = rh.gac(this, R.attr.viewPortbackgroundColor)
|
||||||
relativeLayout.addView(graph)
|
relativeLayout.addView(graph)
|
||||||
|
|
||||||
val label = TextView(this)
|
val label = TextView(this)
|
||||||
|
@ -304,17 +284,7 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
@Suppress("SameParameterValue")
|
@Suppress("SameParameterValue")
|
||||||
private fun loadAll(from: String) {
|
private fun loadAll(from: String) {
|
||||||
updateDate()
|
updateDate()
|
||||||
Thread {
|
runCalculation(from)
|
||||||
overviewData.prepareBgData("$from")
|
|
||||||
overviewData.prepareTreatmentsData(from)
|
|
||||||
rxBus.send(EventRefreshOverview("loadAll_$from"))
|
|
||||||
overviewData.prepareTemporaryTargetData(from)
|
|
||||||
rxBus.send(EventRefreshOverview("loadAll_$from"))
|
|
||||||
overviewData.prepareBasalData(from)
|
|
||||||
rxBus.send(EventRefreshOverview(from))
|
|
||||||
aapsLogger.debug(LTag.UI, "loadAll $from finished")
|
|
||||||
runCalculation(from)
|
|
||||||
}.start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setTime(start: Long) {
|
private fun setTime(start: Long) {
|
||||||
|
@ -335,25 +305,32 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runCalculation(from: String) {
|
private fun runCalculation(from: String) {
|
||||||
Thread {
|
calculationWorkflow.runCalculation(
|
||||||
iobCobCalculator.stopCalculation(from)
|
CalculationWorkflow.HISTORY_CALCULATION,
|
||||||
iobCobCalculator.stopCalculationTrigger = false
|
iobCobCalculator,
|
||||||
iobCobCalculator.runCalculation(from, overviewData.toTime, bgDataReload = true, limitDataToOldestAvailable = false, cause = EventCustomCalculationFinished())
|
overviewData,
|
||||||
}.start()
|
from,
|
||||||
|
overviewData.toTime,
|
||||||
|
bgDataReload = true,
|
||||||
|
limitDataToOldestAvailable = false,
|
||||||
|
cause = EventCustomCalculationFinished(),
|
||||||
|
runLoop = false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Volatile
|
@Volatile
|
||||||
var runningRefresh = false
|
var runningRefresh = false
|
||||||
|
|
||||||
|
@Suppress("SameParameterValue")
|
||||||
private fun refreshLoop(from: String) {
|
private fun refreshLoop(from: String) {
|
||||||
if (runningRefresh) return
|
if (runningRefresh) return
|
||||||
runningRefresh = true
|
runningRefresh = true
|
||||||
overviewData.prepareIobAutosensData(from)
|
|
||||||
rxBus.send(EventRefreshOverview(from))
|
rxBus.send(EventRefreshOverview(from))
|
||||||
aapsLogger.debug(LTag.UI, "refreshLoop finished")
|
aapsLogger.debug(LTag.UI, "refreshLoop finished")
|
||||||
runningRefresh = false
|
runningRefresh = false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateDate() {
|
private fun updateDate() {
|
||||||
binding.date.text = dateUtil.dateAndTimeString(overviewData.fromTime)
|
binding.date.text = dateUtil.dateAndTimeString(overviewData.fromTime)
|
||||||
binding.zoom.text = rangeToDisplay.toString()
|
binding.zoom.text = rangeToDisplay.toString()
|
||||||
}
|
}
|
||||||
|
@ -372,6 +349,8 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
graphData.addBgReadings(menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal])
|
graphData.addBgReadings(menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal])
|
||||||
if (buildHelper.isDev()) graphData.addBucketedData()
|
if (buildHelper.isDev()) graphData.addBucketedData()
|
||||||
graphData.addTreatments()
|
graphData.addTreatments()
|
||||||
|
if (menuChartSettings[0][OverviewMenus.CharType.TREAT.ordinal])
|
||||||
|
graphData.addTherapyEvents()
|
||||||
if (menuChartSettings[0][OverviewMenus.CharType.ACT.ordinal])
|
if (menuChartSettings[0][OverviewMenus.CharType.ACT.ordinal])
|
||||||
graphData.addActivity(0.8)
|
graphData.addActivity(0.8)
|
||||||
if (pump.pumpDescription.isTempBasalCapable && menuChartSettings[0][OverviewMenus.CharType.BAS.ordinal])
|
if (pump.pumpDescription.isTempBasalCapable && menuChartSettings[0][OverviewMenus.CharType.BAS.ordinal])
|
||||||
|
@ -400,12 +379,12 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
var useDSForScale = false
|
var useDSForScale = false
|
||||||
var useBGIForScale = false
|
var useBGIForScale = false
|
||||||
when {
|
when {
|
||||||
menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true
|
menuChartSettings[g + 1][OverviewMenus.CharType.ABS.ordinal] -> useABSForScale = true
|
||||||
menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true
|
menuChartSettings[g + 1][OverviewMenus.CharType.IOB.ordinal] -> useIobForScale = true
|
||||||
menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true
|
menuChartSettings[g + 1][OverviewMenus.CharType.COB.ordinal] -> useCobForScale = true
|
||||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true
|
menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] -> useDevForScale = true
|
||||||
menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] -> useBGIForScale = true
|
menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal] -> useBGIForScale = true
|
||||||
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true
|
menuChartSettings[g + 1][OverviewMenus.CharType.SEN.ordinal] -> useRatioForScale = true
|
||||||
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true
|
menuChartSettings[g + 1][OverviewMenus.CharType.DEVSLOPE.ordinal] -> useDSForScale = true
|
||||||
}
|
}
|
||||||
val alignDevBgiScale = menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]
|
val alignDevBgiScale = menuChartSettings[g + 1][OverviewMenus.CharType.DEV.ordinal] && menuChartSettings[g + 1][OverviewMenus.CharType.BGI.ordinal]
|
||||||
|
@ -437,4 +416,9 @@ class HistoryBrowseActivity : NoSplashAppCompatActivity() {
|
||||||
secondaryGraphsData[g].performUpdate()
|
secondaryGraphsData[g].performUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateCalcProgress(percent: Int) {
|
||||||
|
binding.progressBar.progress = percent
|
||||||
|
binding.progressBar.visibility = (percent != 100).toVisibilityKeepSpace()
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -8,17 +8,17 @@ import android.os.Bundle
|
||||||
import androidx.annotation.XmlRes
|
import androidx.annotation.XmlRes
|
||||||
import androidx.preference.*
|
import androidx.preference.*
|
||||||
import dagger.android.support.AndroidSupportInjection
|
import dagger.android.support.AndroidSupportInjection
|
||||||
import info.nightscout.androidaps.interfaces.Config
|
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin
|
import info.nightscout.androidaps.danaRKorean.DanaRKoreanPlugin
|
||||||
import info.nightscout.androidaps.danaRv2.DanaRv2Plugin
|
import info.nightscout.androidaps.danaRv2.DanaRv2Plugin
|
||||||
import info.nightscout.androidaps.danar.DanaRPlugin
|
import info.nightscout.androidaps.danar.DanaRPlugin
|
||||||
import info.nightscout.androidaps.danars.DanaRSPlugin
|
import info.nightscout.androidaps.danars.DanaRSPlugin
|
||||||
import info.nightscout.androidaps.diaconn.DiaconnG8Plugin
|
import info.nightscout.androidaps.diaconn.DiaconnG8Plugin
|
||||||
import info.nightscout.androidaps.interfaces.Profile
|
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||||
import info.nightscout.androidaps.events.EventRebuildTabs
|
import info.nightscout.androidaps.events.EventRebuildTabs
|
||||||
|
import info.nightscout.androidaps.interfaces.Config
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase
|
import info.nightscout.androidaps.interfaces.PluginBase
|
||||||
|
import info.nightscout.androidaps.interfaces.Profile
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.androidaps.plugin.general.openhumans.OpenHumansUploader
|
import info.nightscout.androidaps.plugin.general.openhumans.OpenHumansUploader
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin
|
||||||
|
@ -44,11 +44,11 @@ import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
|
||||||
import info.nightscout.androidaps.plugins.source.*
|
import info.nightscout.androidaps.plugins.source.*
|
||||||
import info.nightscout.shared.SafeParse
|
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog.show
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog.show
|
||||||
import info.nightscout.androidaps.utils.protection.PasswordCheck
|
import info.nightscout.androidaps.utils.protection.PasswordCheck
|
||||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck.ProtectionType.*
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.shared.SafeParse
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -236,7 +236,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
||||||
rh.gs(R.string.key_application_protection) == key ||
|
rh.gs(R.string.key_application_protection) == key ||
|
||||||
rh.gs(R.string.key_bolus_protection) == key) &&
|
rh.gs(R.string.key_bolus_protection) == key) &&
|
||||||
sp.getString(R.string.key_master_password, "") == "" &&
|
sp.getString(R.string.key_master_password, "") == "" &&
|
||||||
sp.getInt(key, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal
|
sp.getInt(key, NONE.ordinal) == BIOMETRIC.ordinal
|
||||||
) {
|
) {
|
||||||
activity?.let {
|
activity?.let {
|
||||||
val title = rh.gs(R.string.unsecure_fallback_biometric)
|
val title = rh.gs(R.string.unsecure_fallback_biometric)
|
||||||
|
@ -246,9 +246,9 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
||||||
}
|
}
|
||||||
|
|
||||||
// Master password erased with activated Biometric protection
|
// Master password erased with activated Biometric protection
|
||||||
val isBiometricActivated = sp.getInt(R.string.key_settings_protection, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal ||
|
val isBiometricActivated = sp.getInt(R.string.key_settings_protection, NONE.ordinal) == BIOMETRIC.ordinal ||
|
||||||
sp.getInt(R.string.key_application_protection, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal ||
|
sp.getInt(R.string.key_application_protection, NONE.ordinal) == BIOMETRIC.ordinal ||
|
||||||
sp.getInt(R.string.key_bolus_protection, ProtectionCheck.ProtectionType.NONE.ordinal) == ProtectionCheck.ProtectionType.BIOMETRIC.ordinal
|
sp.getInt(R.string.key_bolus_protection, NONE.ordinal) == BIOMETRIC.ordinal
|
||||||
if (rh.gs(R.string.key_master_password) == key && sp.getString(key, "") == "" && isBiometricActivated) {
|
if (rh.gs(R.string.key_master_password) == key && sp.getString(key, "") == "" && isBiometricActivated) {
|
||||||
activity?.let {
|
activity?.let {
|
||||||
val title = rh.gs(R.string.unsecure_fallback_biometric)
|
val title = rh.gs(R.string.unsecure_fallback_biometric)
|
||||||
|
@ -319,26 +319,35 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
||||||
if (pref is ListPreference) {
|
if (pref is ListPreference) {
|
||||||
pref.setSummary(pref.entry)
|
pref.setSummary(pref.entry)
|
||||||
// Preferences
|
// Preferences
|
||||||
// Preferences
|
|
||||||
if (pref.getKey() == rh.gs(R.string.key_settings_protection)) {
|
if (pref.getKey() == rh.gs(R.string.key_settings_protection)) {
|
||||||
val pass: Preference? = findPreference(rh.gs(R.string.key_settings_password))
|
val pass: Preference? = findPreference(rh.gs(R.string.key_settings_password))
|
||||||
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.CUSTOM_PASSWORD.ordinal.toString()
|
val usePassword = pref.value == CUSTOM_PASSWORD.ordinal.toString()
|
||||||
|
pass?.let { it.isVisible = usePassword }
|
||||||
|
val pin: Preference? = findPreference(rh.gs(R.string.key_settings_pin))
|
||||||
|
val usePin = pref.value == CUSTOM_PIN.ordinal.toString()
|
||||||
|
pin?.let { it.isVisible = usePin }
|
||||||
}
|
}
|
||||||
// Application
|
// Application
|
||||||
// Application
|
|
||||||
if (pref.getKey() == rh.gs(R.string.key_application_protection)) {
|
if (pref.getKey() == rh.gs(R.string.key_application_protection)) {
|
||||||
val pass: Preference? = findPreference(rh.gs(R.string.key_application_password))
|
val pass: Preference? = findPreference(rh.gs(R.string.key_application_password))
|
||||||
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.CUSTOM_PASSWORD.ordinal.toString()
|
val usePassword = pref.value == CUSTOM_PASSWORD.ordinal.toString()
|
||||||
|
pass?.let { it.isVisible = usePassword }
|
||||||
|
val pin: Preference? = findPreference(rh.gs(R.string.key_application_pin))
|
||||||
|
val usePin = pref.value == CUSTOM_PIN.ordinal.toString()
|
||||||
|
pin?.let { it.isVisible = usePin }
|
||||||
}
|
}
|
||||||
// Bolus
|
// Bolus
|
||||||
// Bolus
|
|
||||||
if (pref.getKey() == rh.gs(R.string.key_bolus_protection)) {
|
if (pref.getKey() == rh.gs(R.string.key_bolus_protection)) {
|
||||||
val pass: Preference? = findPreference(rh.gs(R.string.key_bolus_password))
|
val pass: Preference? = findPreference(rh.gs(R.string.key_bolus_password))
|
||||||
if (pass != null) pass.isEnabled = pref.value == ProtectionCheck.ProtectionType.CUSTOM_PASSWORD.ordinal.toString()
|
val usePassword = pref.value == CUSTOM_PASSWORD.ordinal.toString()
|
||||||
|
pass?.let { it.isVisible = usePassword }
|
||||||
|
val pin: Preference? = findPreference(rh.gs(R.string.key_bolus_pin))
|
||||||
|
val usePin = pref.value == CUSTOM_PIN.ordinal.toString()
|
||||||
|
pin?.let { it.isVisible = usePin }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pref is EditTextPreference) {
|
if (pref is EditTextPreference) {
|
||||||
if (pref.getKey().contains("password") || pref.getKey().contains("secret")) {
|
if (pref.getKey().contains("password") || pref.getKey().contains("pin") || pref.getKey().contains("secret")) {
|
||||||
pref.setSummary("******")
|
pref.setSummary("******")
|
||||||
} else if (pref.text != null) {
|
} else if (pref.text != null) {
|
||||||
pref.dialogMessage = pref.dialogMessage
|
pref.dialogMessage = pref.dialogMessage
|
||||||
|
@ -354,7 +363,10 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
||||||
rh.gs(R.string.key_bolus_password),
|
rh.gs(R.string.key_bolus_password),
|
||||||
rh.gs(R.string.key_master_password),
|
rh.gs(R.string.key_master_password),
|
||||||
rh.gs(R.string.key_application_password),
|
rh.gs(R.string.key_application_password),
|
||||||
rh.gs(R.string.key_settings_password)
|
rh.gs(R.string.key_settings_password),
|
||||||
|
rh.gs(R.string.key_bolus_pin),
|
||||||
|
rh.gs(R.string.key_application_pin),
|
||||||
|
rh.gs(R.string.key_settings_pin)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (pref is Preference) {
|
if (pref is Preference) {
|
||||||
|
@ -362,7 +374,11 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
||||||
if (sp.getString(pref.key, "").startsWith("hmac:")) {
|
if (sp.getString(pref.key, "").startsWith("hmac:")) {
|
||||||
pref.summary = "******"
|
pref.summary = "******"
|
||||||
} else {
|
} else {
|
||||||
pref.summary = rh.gs(R.string.password_not_set)
|
if (pref.key.contains("pin")) {
|
||||||
|
pref.summary = rh.gs(R.string.pin_not_set)
|
||||||
|
}else {
|
||||||
|
pref.summary = rh.gs(R.string.password_not_set)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -408,6 +424,18 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang
|
||||||
passwordCheck.setPassword(context, R.string.application_password, R.string.key_application_password)
|
passwordCheck.setPassword(context, R.string.application_password, R.string.key_application_password)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if (preference.key == rh.gs(R.string.key_settings_pin)) {
|
||||||
|
passwordCheck.setPassword(context, R.string.settings_pin, R.string.key_settings_pin, pinInput = true)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (preference.key == rh.gs(R.string.key_bolus_pin)) {
|
||||||
|
passwordCheck.setPassword(context, R.string.bolus_pin, R.string.key_bolus_pin, pinInput = true)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (preference.key == rh.gs(R.string.key_application_pin)) {
|
||||||
|
passwordCheck.setPassword(context, R.string.application_pin, R.string.key_application_pin, pinInput = true)
|
||||||
|
return true
|
||||||
|
}
|
||||||
// NSClient copy settings
|
// NSClient copy settings
|
||||||
if (preference.key == rh.gs(R.string.key_statuslights_copy_ns)) {
|
if (preference.key == rh.gs(R.string.key_statuslights_copy_ns)) {
|
||||||
nsSettingStatus.copyStatusLightsNsSettings(context)
|
nsSettingStatus.copyStatusLightsNsSettings(context)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
import android.view.MenuItem
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
@ -19,6 +20,7 @@ class PreferencesActivity : NoSplashAppCompatActivity(), PreferenceFragmentCompa
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
setTheme(R.style.AppTheme)
|
||||||
binding = ActivityPreferencesBinding.inflate(layoutInflater)
|
binding = ActivityPreferencesBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
@ -61,4 +63,14 @@ class PreferencesActivity : NoSplashAppCompatActivity(), PreferenceFragmentCompa
|
||||||
private fun filterPreferences() {
|
private fun filterPreferences() {
|
||||||
myPreferenceFragment?.setFilter(binding.prefFilter.text.toString())
|
myPreferenceFragment?.setFilter(binding.prefFilter.text.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
android.R.id.home -> {
|
||||||
|
onBackPressed()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.widget.PopupMenu
|
import android.widget.PopupMenu
|
||||||
|
import android.widget.TextView
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.data.ProfileSealed
|
import info.nightscout.androidaps.data.ProfileSealed
|
||||||
import info.nightscout.androidaps.data.PureProfile
|
import info.nightscout.androidaps.data.PureProfile
|
||||||
|
@ -37,7 +38,6 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||||
@Inject lateinit var defaultProfile: DefaultProfile
|
@Inject lateinit var defaultProfile: DefaultProfile
|
||||||
@Inject lateinit var defaultProfileDPV: DefaultProfileDPV
|
@Inject lateinit var defaultProfileDPV: DefaultProfileDPV
|
||||||
@Inject lateinit var localProfilePlugin: LocalProfilePlugin
|
@Inject lateinit var localProfilePlugin: LocalProfilePlugin
|
||||||
@Inject lateinit var rxBus: RxBus
|
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
@Inject lateinit var activePlugin: ActivePlugin
|
@Inject lateinit var activePlugin: ActivePlugin
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
|
@ -66,9 +66,9 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
private lateinit var binding: ActivityProfilehelperBinding
|
private lateinit var binding: ActivityProfilehelperBinding
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
binding = ActivityProfilehelperBinding.inflate(layoutInflater)
|
binding = ActivityProfilehelperBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
@ -79,11 +79,11 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||||
switchTab(1, typeSelected[1])
|
switchTab(1, typeSelected[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.profiletype.setOnClickListener {
|
binding.profileType.setOnClickListener {
|
||||||
PopupMenu(this, binding.profiletype).apply {
|
PopupMenu(this, binding.profileType).apply {
|
||||||
menuInflater.inflate(R.menu.menu_profilehelper, menu)
|
menuInflater.inflate(R.menu.menu_profilehelper, menu)
|
||||||
setOnMenuItemClickListener { item ->
|
setOnMenuItemClickListener { item ->
|
||||||
binding.profiletype.setText(item.title)
|
binding.profileType.setText(item.title)
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.menu_default -> switchTab(tabSelected, ProfileType.MOTOL_DEFAULT)
|
R.id.menu_default -> switchTab(tabSelected, ProfileType.MOTOL_DEFAULT)
|
||||||
R.id.menu_default_dpv -> switchTab(tabSelected, ProfileType.DPV_DEFAULT)
|
R.id.menu_default_dpv -> switchTab(tabSelected, ProfileType.DPV_DEFAULT)
|
||||||
|
@ -130,7 +130,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default profile
|
// Default profile
|
||||||
binding.copytolocalprofile.setOnClickListener {
|
binding.copyToLocalProfile.setOnClickListener {
|
||||||
storeValues()
|
storeValues()
|
||||||
val age = ageUsed[tabSelected]
|
val age = ageUsed[tabSelected]
|
||||||
val weight = weightUsed[tabSelected]
|
val weight = weightUsed[tabSelected]
|
||||||
|
@ -168,20 +168,22 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
binding.basalpctfromtdd.setParams(32.0, 32.0, 37.0, 1.0, DecimalFormat("0"), false, null)
|
binding.basalPctFromTdd.setParams(32.0, 32.0, 37.0, 1.0, DecimalFormat("0"), false, null)
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
binding.tdds.addView(TextView(this).apply { text = rh.gs(R.string.tdd) + ": " + rh.gs(R.string.calculation_in_progress) })
|
||||||
binding.tdds.text = getString(R.string.tdd) + ": " + rh.gs(R.string.calculation_in_progress)
|
|
||||||
Thread {
|
Thread {
|
||||||
val tdds = tddCalculator.stats()
|
val tdds = tddCalculator.stats(this)
|
||||||
runOnUiThread { binding.tdds.text = tdds }
|
runOnUiThread {
|
||||||
|
binding.tdds.removeAllViews()
|
||||||
|
binding.tdds.addView(tdds)
|
||||||
|
}
|
||||||
}.start()
|
}.start()
|
||||||
|
|
||||||
// Current profile
|
// Current profile
|
||||||
binding.currentProfileText.text = profileFunction.getProfileName()
|
binding.currentProfileText.text = profileFunction.getProfileName()
|
||||||
|
|
||||||
// General
|
// General
|
||||||
binding.compareprofile.setOnClickListener {
|
binding.compareProfiles.setOnClickListener {
|
||||||
storeValues()
|
storeValues()
|
||||||
for (i in 0..1) {
|
for (i in 0..1) {
|
||||||
if (typeSelected[i] == ProfileType.MOTOL_DEFAULT) {
|
if (typeSelected[i] == ProfileType.MOTOL_DEFAULT) {
|
||||||
|
@ -239,10 +241,10 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||||
}
|
}
|
||||||
ToastUtils.showToastInUiThread(this, R.string.invalidinput)
|
ToastUtils.showToastInUiThread(this, R.string.invalidinput)
|
||||||
}
|
}
|
||||||
binding.age.editText?.id?.let { binding.ageLabel.labelFor = it }
|
binding.ageLabel.labelFor = binding.age.editTextId
|
||||||
binding.tdd.editText?.id?.let { binding.tddLabel.labelFor = it }
|
binding.tddLabel.labelFor = binding.tdd.editTextId
|
||||||
binding.weight.editText?.id?.let { binding.weightLabel.labelFor = it }
|
binding.weightLabel.labelFor = binding.weight.editTextId
|
||||||
binding.basalpctfromtdd.editText?.id?.let { binding.basalpctfromtddLabel.labelFor = it }
|
binding.basalPctFromTddLabel.labelFor = binding.basalPctFromTdd.editTextId
|
||||||
|
|
||||||
switchTab(0, typeSelected[0], false)
|
switchTab(0, typeSelected[0], false)
|
||||||
}
|
}
|
||||||
|
@ -273,7 +275,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||||
ageUsed[tabSelected] = binding.age.value
|
ageUsed[tabSelected] = binding.age.value
|
||||||
weightUsed[tabSelected] = binding.weight.value
|
weightUsed[tabSelected] = binding.weight.value
|
||||||
tddUsed[tabSelected] = binding.tdd.value
|
tddUsed[tabSelected] = binding.tdd.value
|
||||||
pctUsed[tabSelected] = binding.basalpctfromtdd.value
|
pctUsed[tabSelected] = binding.basalPctFromTdd.value
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun switchTab(tab: Int, newContent: ProfileType, storeOld: Boolean = true) {
|
private fun switchTab(tab: Int, newContent: ProfileType, storeOld: Boolean = true) {
|
||||||
|
@ -283,10 +285,10 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
tabSelected = tab
|
tabSelected = tab
|
||||||
typeSelected[tabSelected] = newContent
|
typeSelected[tabSelected] = newContent
|
||||||
binding.profiletypeTitle.defaultHintTextColor = ColorStateList.valueOf(rh.gc(if (tab == 0) R.color.helperProfile else R.color.examinedProfile))
|
binding.profileTypeTitle.defaultHintTextColor = ColorStateList.valueOf(rh.gac( this, if (tab == 0) R.attr.helperProfileColor else R.attr.examinedProfileColor))
|
||||||
|
|
||||||
// show new content
|
// show new content
|
||||||
binding.profiletype.setText(
|
binding.profileType.setText(
|
||||||
when (typeSelected[tabSelected]) {
|
when (typeSelected[tabSelected]) {
|
||||||
ProfileType.MOTOL_DEFAULT -> rh.gs(R.string.motoldefaultprofile)
|
ProfileType.MOTOL_DEFAULT -> rh.gs(R.string.motoldefaultprofile)
|
||||||
ProfileType.DPV_DEFAULT -> rh.gs(R.string.dpvdefaultprofile)
|
ProfileType.DPV_DEFAULT -> rh.gs(R.string.dpvdefaultprofile)
|
||||||
|
@ -304,9 +306,9 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||||
binding.age.value = ageUsed[tabSelected]
|
binding.age.value = ageUsed[tabSelected]
|
||||||
binding.weight.value = weightUsed[tabSelected]
|
binding.weight.value = weightUsed[tabSelected]
|
||||||
binding.tdd.value = tddUsed[tabSelected]
|
binding.tdd.value = tddUsed[tabSelected]
|
||||||
binding.basalpctfromtdd.value = pctUsed[tabSelected]
|
binding.basalPctFromTdd.value = pctUsed[tabSelected]
|
||||||
|
|
||||||
binding.basalpctfromtddRow.visibility = (newContent == ProfileType.DPV_DEFAULT).toVisibility()
|
binding.basalPctFromTddRow.visibility = (newContent == ProfileType.DPV_DEFAULT).toVisibility()
|
||||||
if (profileList.isNotEmpty())
|
if (profileList.isNotEmpty())
|
||||||
binding.availableProfileList.setText(profileList[profileUsed[tabSelected]].toString())
|
binding.availableProfileList.setText(profileList[profileUsed[tabSelected]].toString())
|
||||||
if (profileSwitch.isNotEmpty())
|
if (profileSwitch.isNotEmpty())
|
||||||
|
@ -314,7 +316,7 @@ class ProfileHelperActivity : NoSplashAppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setBackgroundColorOnSelected(tab: Int) {
|
private fun setBackgroundColorOnSelected(tab: Int) {
|
||||||
binding.menu1.setBackgroundColor(rh.gc(if (tab == 1) R.color.defaultbackground else R.color.helperProfile))
|
binding.menu1.setBackgroundColor(rh.gac(this, if (tab == 1) R.attr.defaultbackground else R.attr.helperProfileColor))
|
||||||
binding.menu2.setBackgroundColor(rh.gc(if (tab == 0) R.color.defaultbackground else R.color.examinedProfile))
|
binding.menu2.setBackgroundColor(rh.gac(this, if (tab == 0) R.attr.defaultbackground else R.attr.examinedProfileColor))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package info.nightscout.androidaps.activities
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.widget.TextView
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
||||||
|
@ -9,7 +10,6 @@ import info.nightscout.androidaps.databinding.ActivityStatsBinding
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.utils.ActivityMonitor
|
import info.nightscout.androidaps.utils.ActivityMonitor
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
|
||||||
import info.nightscout.androidaps.utils.stats.TddCalculator
|
import info.nightscout.androidaps.utils.stats.TddCalculator
|
||||||
import info.nightscout.androidaps.utils.stats.TirCalculator
|
import info.nightscout.androidaps.utils.stats.TirCalculator
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -29,21 +29,30 @@ class StatsActivity : NoSplashAppCompatActivity() {
|
||||||
binding = ActivityStatsBinding.inflate(layoutInflater)
|
binding = ActivityStatsBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
binding.tdds.text = getString(R.string.tdd) + ": " + rh.gs(R.string.calculation_in_progress)
|
binding.tdds.addView(TextView(this).apply { text = getString(R.string.tdd) + ": " + rh.gs(R.string.calculation_in_progress) })
|
||||||
binding.tir.text = getString(R.string.tir) + ": " + rh.gs(R.string.calculation_in_progress)
|
binding.tir.addView(TextView(this).apply { text = getString(R.string.tir) + ": " + rh.gs(R.string.calculation_in_progress) })
|
||||||
binding.activity.text = rh.gs(R.string.activitymonitor) + ": " + rh.gs(R.string.calculation_in_progress)
|
binding.activity.addView(TextView(this).apply { text = getString(R.string.activitymonitor) + ": " + rh.gs(R.string.calculation_in_progress) })
|
||||||
|
|
||||||
Thread {
|
Thread {
|
||||||
val tdds = tddCalculator.stats()
|
val tdds = tddCalculator.stats(this)
|
||||||
runOnUiThread { binding.tdds.text = tdds }
|
runOnUiThread {
|
||||||
|
binding.tdds.removeAllViews()
|
||||||
|
binding.tdds.addView(tdds)
|
||||||
|
}
|
||||||
}.start()
|
}.start()
|
||||||
Thread {
|
Thread {
|
||||||
val tir = tirCalculator.stats()
|
val tir = tirCalculator.stats(this)
|
||||||
runOnUiThread { binding.tir.text = tir }
|
runOnUiThread {
|
||||||
|
binding.tir.removeAllViews()
|
||||||
|
binding.tir.addView(tir)
|
||||||
|
}
|
||||||
}.start()
|
}.start()
|
||||||
Thread {
|
Thread {
|
||||||
val activity = activityMonitor.stats()
|
val activity = activityMonitor.stats(this)
|
||||||
runOnUiThread { binding.activity.text = activity }
|
runOnUiThread {
|
||||||
|
binding.activity.removeAllViews()
|
||||||
|
binding.activity.addView(activity)
|
||||||
|
}
|
||||||
}.start()
|
}.start()
|
||||||
|
|
||||||
binding.ok.setOnClickListener { finish() }
|
binding.ok.setOnClickListener { finish() }
|
||||||
|
|
|
@ -43,9 +43,9 @@ class SurveyActivity : NoSplashAppCompatActivity() {
|
||||||
val profileList = profileStore?.getProfileList() ?: return
|
val profileList = profileStore?.getProfileList() ?: return
|
||||||
binding.spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList)
|
binding.spinner.adapter = ArrayAdapter(this, R.layout.spinner_centered, profileList)
|
||||||
|
|
||||||
binding.tdds.text = tddCalculator.stats()
|
//binding.tdds.text = tddCalculator.stats()
|
||||||
binding.tir.text = tirCalculator.stats()
|
//binding.tir.text = tirCalculator.stats()
|
||||||
binding.activity.text = activityMonitor.stats()
|
//binding.activity.text = activityMonitor.stats()
|
||||||
|
|
||||||
binding.profile.setOnClickListener {
|
binding.profile.setOnClickListener {
|
||||||
val age = SafeParse.stringToDouble(binding.age.text.toString())
|
val age = SafeParse.stringToDouble(binding.age.text.toString())
|
||||||
|
@ -104,7 +104,7 @@ class SurveyActivity : NoSplashAppCompatActivity() {
|
||||||
.addOnCompleteListener(this) { task ->
|
.addOnCompleteListener(this) { task ->
|
||||||
if (task.isSuccessful) {
|
if (task.isSuccessful) {
|
||||||
aapsLogger.debug(LTag.CORE, "signInAnonymously:success")
|
aapsLogger.debug(LTag.CORE, "signInAnonymously:success")
|
||||||
//val user = auth.currentUser // TODO: do we need this, seems unused?
|
//val user = auth.currentUser // do we need this, seems unused?
|
||||||
|
|
||||||
val database = FirebaseDatabase.getInstance().reference
|
val database = FirebaseDatabase.getInstance().reference
|
||||||
database.child("survey").child(r.id).setValue(r)
|
database.child("survey").child(r.id).setValue(r)
|
||||||
|
|
|
@ -2,12 +2,14 @@ package info.nightscout.androidaps.activities
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentTransaction
|
import androidx.fragment.app.FragmentTransaction
|
||||||
|
import com.google.android.material.tabs.TabLayout
|
||||||
|
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.activities.fragments.*
|
import info.nightscout.androidaps.activities.fragments.*
|
||||||
import info.nightscout.androidaps.databinding.TreatmentsFragmentBinding
|
import info.nightscout.androidaps.databinding.TreatmentsFragmentBinding
|
||||||
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -23,49 +25,34 @@ class TreatmentsActivity : NoSplashAppCompatActivity() {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
binding = TreatmentsFragmentBinding.inflate(layoutInflater)
|
binding = TreatmentsFragmentBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
//binding.tempBasals.visibility = buildHelper.isEngineeringMode().toVisibility()
|
|
||||||
//binding.extendedBoluses.visibility = (buildHelper.isEngineeringMode() && !activePlugin.activePump.isFakingTempsByExtendedBoluses).toVisibility()
|
|
||||||
|
|
||||||
binding.treatments.setOnClickListener {
|
// Use index, TabItems crashes with an id
|
||||||
setFragment(TreatmentsBolusCarbsFragment())
|
val useFakeTempBasal = activePlugin.activePump.isFakingTempsByExtendedBoluses
|
||||||
setBackgroundColorOnSelected(it)
|
binding.treatmentsTabs.getTabAt(1)?.view?.visibility = useFakeTempBasal.toVisibility()
|
||||||
supportActionBar?.title = rh.gs(R.string.carbs_and_bolus)
|
|
||||||
}
|
|
||||||
binding.extendedBoluses.setOnClickListener {
|
|
||||||
setFragment(TreatmentsExtendedBolusesFragment())
|
|
||||||
setBackgroundColorOnSelected(it)
|
|
||||||
supportActionBar?.title = rh.gs(R.string.extended_bolus)
|
|
||||||
}
|
|
||||||
binding.tempBasals.setOnClickListener {
|
|
||||||
setFragment(TreatmentsTemporaryBasalsFragment())
|
|
||||||
setBackgroundColorOnSelected(it)
|
|
||||||
supportActionBar?.title = rh.gs(R.string.tempbasal_label)
|
|
||||||
}
|
|
||||||
binding.tempTargets.setOnClickListener {
|
|
||||||
setFragment(TreatmentsTempTargetFragment())
|
|
||||||
setBackgroundColorOnSelected(it)
|
|
||||||
supportActionBar?.title = rh.gs(R.string.tempt_targets)
|
|
||||||
}
|
|
||||||
binding.profileSwitches.setOnClickListener {
|
|
||||||
setFragment(TreatmentsProfileSwitchFragment())
|
|
||||||
setBackgroundColorOnSelected(it)
|
|
||||||
supportActionBar?.title = rh.gs(R.string.profile_changes)
|
|
||||||
}
|
|
||||||
binding.careportal.setOnClickListener {
|
|
||||||
setFragment(TreatmentsCareportalFragment())
|
|
||||||
setBackgroundColorOnSelected(it)
|
|
||||||
supportActionBar?.title = rh.gs(R.string.careportal)
|
|
||||||
}
|
|
||||||
binding.userentry.setOnClickListener {
|
|
||||||
setFragment(TreatmentsUserEntryFragment())
|
|
||||||
setBackgroundColorOnSelected(it)
|
|
||||||
supportActionBar?.title = rh.gs(R.string.user_action)
|
|
||||||
}
|
|
||||||
setFragment(TreatmentsBolusCarbsFragment())
|
setFragment(TreatmentsBolusCarbsFragment())
|
||||||
setBackgroundColorOnSelected(binding.treatments)
|
|
||||||
setSupportActionBar(binding.toolbar)
|
setSupportActionBar(binding.toolbar)
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
supportActionBar?.title = rh.gs(R.string.carbs_and_bolus)
|
supportActionBar?.title = rh.gs(R.string.carbs_and_bolus)
|
||||||
|
|
||||||
|
binding.treatmentsTabs.addOnTabSelectedListener(object : OnTabSelectedListener {
|
||||||
|
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||||
|
val fragment = when (tab.position) {
|
||||||
|
0 -> TreatmentsBolusCarbsFragment::class.java
|
||||||
|
1 -> TreatmentsExtendedBolusesFragment::class.java
|
||||||
|
2 -> TreatmentsTemporaryBasalsFragment::class.java
|
||||||
|
3 -> TreatmentsTempTargetFragment::class.java
|
||||||
|
4 -> TreatmentsProfileSwitchFragment::class.java
|
||||||
|
5 -> TreatmentsCareportalFragment::class.java
|
||||||
|
else -> TreatmentsUserEntryFragment::class.java
|
||||||
|
}
|
||||||
|
setFragment(fragment.newInstance())
|
||||||
|
supportActionBar?.title = tab.contentDescription
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTabUnselected(tab: TabLayout.Tab) {}
|
||||||
|
override fun onTabReselected(tab: TabLayout.Tab) {}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
@ -86,15 +73,4 @@ class TreatmentsActivity : NoSplashAppCompatActivity() {
|
||||||
.commit()
|
.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setBackgroundColorOnSelected(selected: View) {
|
|
||||||
binding.treatments.setBackgroundColor(rh.gc(R.color.defaultbackground))
|
|
||||||
binding.extendedBoluses.setBackgroundColor(rh.gc(R.color.defaultbackground))
|
|
||||||
binding.tempBasals.setBackgroundColor(rh.gc(R.color.defaultbackground))
|
|
||||||
binding.tempTargets.setBackgroundColor(rh.gc(R.color.defaultbackground))
|
|
||||||
binding.profileSwitches.setBackgroundColor(rh.gc(R.color.defaultbackground))
|
|
||||||
binding.careportal.setBackgroundColor(rh.gc(R.color.defaultbackground))
|
|
||||||
binding.userentry.setBackgroundColor(rh.gc(R.color.defaultbackground))
|
|
||||||
selected.setBackgroundColor(rh.gc(R.color.tabBgColorSelected))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,8 @@ package info.nightscout.androidaps.activities.fragments
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.widget.CompoundButton
|
|
||||||
import android.view.ActionMode
|
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.util.forEach
|
import androidx.core.util.forEach
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
@ -18,6 +14,7 @@ import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.database.entities.Bolus
|
import info.nightscout.androidaps.database.entities.Bolus
|
||||||
import info.nightscout.androidaps.database.entities.BolusCalculatorResult
|
import info.nightscout.androidaps.database.entities.BolusCalculatorResult
|
||||||
import info.nightscout.androidaps.database.entities.Carbs
|
import info.nightscout.androidaps.database.entities.Carbs
|
||||||
|
import info.nightscout.androidaps.database.entities.UserEntry
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
||||||
import info.nightscout.androidaps.database.entities.ValueWithUnit
|
import info.nightscout.androidaps.database.entities.ValueWithUnit
|
||||||
|
@ -28,9 +25,7 @@ import info.nightscout.androidaps.database.transactions.InvalidateCarbsTransacti
|
||||||
import info.nightscout.androidaps.databinding.TreatmentsBolusCarbsFragmentBinding
|
import info.nightscout.androidaps.databinding.TreatmentsBolusCarbsFragmentBinding
|
||||||
import info.nightscout.androidaps.databinding.TreatmentsBolusCarbsItemBinding
|
import info.nightscout.androidaps.databinding.TreatmentsBolusCarbsItemBinding
|
||||||
import info.nightscout.androidaps.dialogs.WizardInfoDialog
|
import info.nightscout.androidaps.dialogs.WizardInfoDialog
|
||||||
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
|
||||||
import info.nightscout.androidaps.events.EventTreatmentChange
|
import info.nightscout.androidaps.events.EventTreatmentChange
|
||||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
|
||||||
import info.nightscout.androidaps.extensions.iobCalc
|
import info.nightscout.androidaps.extensions.iobCalc
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
|
@ -39,9 +34,11 @@ import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
|
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
|
||||||
|
import info.nightscout.androidaps.utils.ActionModeHelper
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
|
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.buildHelper.BuildHelper
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
@ -72,8 +69,10 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
@Inject lateinit var activePlugin: ActivePlugin
|
@Inject lateinit var activePlugin: ActivePlugin
|
||||||
|
|
||||||
private var _binding: TreatmentsBolusCarbsFragmentBinding? = null
|
private var _binding: TreatmentsBolusCarbsFragmentBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and onDestroyView.
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
private var menu: Menu? = null
|
||||||
|
|
||||||
class MealLink(
|
class MealLink(
|
||||||
val bolus: Bolus? = null,
|
val bolus: Bolus? = null,
|
||||||
|
@ -82,23 +81,24 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
)
|
)
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
private lateinit var actionHelper: ActionModeHelper<MealLink>
|
||||||
private val millsToThePast = T.days(30).msecs()
|
private val millsToThePast = T.days(30).msecs()
|
||||||
|
|
||||||
private var selectedItems: SparseArray<MealLink> = SparseArray()
|
|
||||||
private var showInvalidated = false
|
private var showInvalidated = false
|
||||||
private var removeActionMode: ActionMode? = null
|
|
||||||
private var toolbar: Toolbar? = null
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||||
TreatmentsBolusCarbsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
TreatmentsBolusCarbsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||||
|
|
||||||
@SuppressLint("CheckResult")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
actionHelper = ActionModeHelper(rh, activity)
|
||||||
|
actionHelper.setUpdateListHandler { binding.recyclerview.adapter?.notifyDataSetChanged() }
|
||||||
|
actionHelper.setOnRemoveHandler { removeSelected(it) }
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
toolbar = activity?.findViewById(R.id.toolbar)
|
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
|
binding.recyclerview.emptyView = binding.noRecordsText
|
||||||
|
binding.recyclerview.loadingView = binding.progressBar
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bolusMealLinksWithInvalid(now: Long) = repository
|
private fun bolusMealLinksWithInvalid(now: Long) = repository
|
||||||
|
@ -127,7 +127,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
|
|
||||||
fun swapAdapter() {
|
fun swapAdapter() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
|
binding.recyclerview.isLoading = true
|
||||||
disposable +=
|
disposable +=
|
||||||
if (showInvalidated)
|
if (showInvalidated)
|
||||||
carbsMealLinksWithInvalid(now)
|
carbsMealLinksWithInvalid(now)
|
||||||
|
@ -169,28 +169,18 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
.debounce(1L, TimeUnit.SECONDS)
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
|
actionHelper.finish()
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
removeActionMode?.let { it.finish() }
|
|
||||||
binding.recyclerview.adapter = null // avoid leaks
|
binding.recyclerview.adapter = null // avoid leaks
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
@ -206,9 +196,9 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
val profile = profileFunction.getProfile() ?: return
|
val profile = profileFunction.getProfile() ?: return
|
||||||
val ml = mealLinks[position]
|
val ml = mealLinks[position]
|
||||||
|
|
||||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(timestamp(ml), timestamp(mealLinks[position - 1]))
|
val newDay = position == 0 || !dateUtil.isSameDayGroup(timestamp(ml), timestamp(mealLinks[position - 1]))
|
||||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
holder.binding.date.visibility = newDay.toVisibility()
|
||||||
holder.binding.date.text = dateUtil.dateString(timestamp(ml))
|
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(timestamp(ml), rh) else ""
|
||||||
|
|
||||||
// Metadata
|
// Metadata
|
||||||
holder.binding.metadataLayout.visibility = (ml.bolusCalculatorResult != null && (ml.bolusCalculatorResult.isValid || showInvalidated)).toVisibility()
|
holder.binding.metadataLayout.visibility = (ml.bolusCalculatorResult != null && (ml.bolusCalculatorResult.isValid || showInvalidated)).toVisibility()
|
||||||
|
@ -226,7 +216,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
holder.binding.bolusInvalid.visibility = bolus.isValid.not().toVisibility()
|
holder.binding.bolusInvalid.visibility = bolus.isValid.not().toVisibility()
|
||||||
val iob = bolus.iobCalc(activePlugin, System.currentTimeMillis(), profile.dia)
|
val iob = bolus.iobCalc(activePlugin, System.currentTimeMillis(), profile.dia)
|
||||||
if (iob.iobContrib > 0.01) {
|
if (iob.iobContrib > 0.01) {
|
||||||
holder.binding.iob.setTextColor(rh.gc(R.color.colorActive))
|
holder.binding.iob.setTextColor(rh.gac(context , R.attr.activeColor))
|
||||||
holder.binding.iob.text = rh.gs(R.string.formatinsulinunits, iob.iobContrib)
|
holder.binding.iob.text = rh.gs(R.string.formatinsulinunits, iob.iobContrib)
|
||||||
holder.binding.iobLabel.visibility = View.VISIBLE
|
holder.binding.iobLabel.visibility = View.VISIBLE
|
||||||
holder.binding.iob.visibility = View.VISIBLE
|
holder.binding.iob.visibility = View.VISIBLE
|
||||||
|
@ -236,13 +226,25 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
holder.binding.iobLabel.visibility = View.GONE
|
holder.binding.iobLabel.visibility = View.GONE
|
||||||
holder.binding.iob.visibility = View.GONE
|
holder.binding.iob.visibility = View.GONE
|
||||||
}
|
}
|
||||||
if (bolus.timestamp > dateUtil.now()) holder.binding.date.setTextColor(rh.gc(R.color.colorScheduled)) else holder.binding.date.setTextColor(holder.binding.carbs.currentTextColor)
|
if (bolus.timestamp > dateUtil.now()) holder.binding.date.setTextColor(rh.gac(context, R.attr.scheduledColor)) else holder.binding.date.setTextColor(holder.binding.carbs
|
||||||
|
.currentTextColor)
|
||||||
holder.binding.mealOrCorrection.text =
|
holder.binding.mealOrCorrection.text =
|
||||||
when (ml.bolus.type) {
|
when (ml.bolus.type) {
|
||||||
Bolus.Type.SMB -> "SMB"
|
Bolus.Type.SMB -> "SMB"
|
||||||
Bolus.Type.NORMAL -> rh.gs(R.string.mealbolus)
|
Bolus.Type.NORMAL -> rh.gs(R.string.mealbolus)
|
||||||
Bolus.Type.PRIMING -> rh.gs(R.string.prime)
|
Bolus.Type.PRIMING -> rh.gs(R.string.prime)
|
||||||
}
|
}
|
||||||
|
holder.binding.cbBolusRemove.visibility = (ml.bolus.isValid && actionHelper.isRemoving).toVisibility()
|
||||||
|
if (actionHelper.isRemoving) {
|
||||||
|
holder.binding.cbBolusRemove.setOnCheckedChangeListener { _, value ->
|
||||||
|
actionHelper.updateSelection(position, ml, value)
|
||||||
|
}
|
||||||
|
holder.binding.root.setOnClickListener {
|
||||||
|
holder.binding.cbBolusRemove.toggle()
|
||||||
|
actionHelper.updateSelection(position, ml, holder.binding.cbBolusRemove.isChecked)
|
||||||
|
}
|
||||||
|
holder.binding.cbBolusRemove.isChecked = actionHelper.isSelected(position)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Carbs
|
// Carbs
|
||||||
holder.binding.carbsLayout.visibility = (ml.carbs != null && (ml.carbs.isValid || showInvalidated)).toVisibility()
|
holder.binding.carbsLayout.visibility = (ml.carbs != null && (ml.carbs.isValid || showInvalidated)).toVisibility()
|
||||||
|
@ -253,26 +255,22 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
holder.binding.carbsNs.visibility = (carbs.interfaceIDs.nightscoutId != null).toVisibility()
|
holder.binding.carbsNs.visibility = (carbs.interfaceIDs.nightscoutId != null).toVisibility()
|
||||||
holder.binding.carbsPump.visibility = (carbs.interfaceIDs.pumpId != null).toVisibility()
|
holder.binding.carbsPump.visibility = (carbs.interfaceIDs.pumpId != null).toVisibility()
|
||||||
holder.binding.carbsInvalid.visibility = carbs.isValid.not().toVisibility()
|
holder.binding.carbsInvalid.visibility = carbs.isValid.not().toVisibility()
|
||||||
}
|
holder.binding.cbCarbsRemove.visibility = (ml.carbs.isValid && actionHelper.isRemoving).toVisibility()
|
||||||
holder.binding.cbBolusRemove.visibility = (ml.bolus?.isValid == true && removeActionMode != null).toVisibility()
|
if (actionHelper.isRemoving) {
|
||||||
holder.binding.cbCarbsRemove.visibility = (ml.carbs?.isValid == true && removeActionMode != null).toVisibility()
|
holder.binding.cbCarbsRemove.setOnCheckedChangeListener { _, value ->
|
||||||
if (removeActionMode != null) {
|
actionHelper.updateSelection(position, ml, value)
|
||||||
val onChange = CompoundButton.OnCheckedChangeListener { _, value ->
|
|
||||||
if (value) {
|
|
||||||
selectedItems.put(position, ml)
|
|
||||||
} else {
|
|
||||||
selectedItems.remove(position)
|
|
||||||
}
|
}
|
||||||
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
|
holder.binding.root.setOnClickListener {
|
||||||
|
holder.binding.cbBolusRemove.toggle()
|
||||||
|
actionHelper.updateSelection(position, ml, holder.binding.cbBolusRemove.isChecked)
|
||||||
|
}
|
||||||
|
holder.binding.cbCarbsRemove.isChecked = actionHelper.isSelected(position)
|
||||||
}
|
}
|
||||||
holder.binding.cbBolusRemove.setOnCheckedChangeListener(onChange)
|
|
||||||
holder.binding.cbBolusRemove.isChecked = selectedItems.get(position) != null
|
|
||||||
holder.binding.cbCarbsRemove.setOnCheckedChangeListener(onChange)
|
|
||||||
holder.binding.cbCarbsRemove.isChecked = selectedItems.get(position) != null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.binding.calculation.tag = ml
|
holder.binding.calculation.tag = ml
|
||||||
val nextTimestamp = if (mealLinks.size != position + 1) timestamp(mealLinks[position + 1]) else 0L
|
val nextTimestamp = if (mealLinks.size != position + 1) timestamp(mealLinks[position + 1]) else 0L
|
||||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(timestamp(ml), nextTimestamp).toVisibility()
|
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(timestamp(ml), nextTimestamp).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount() = mealLinks.size
|
override fun getItemCount() = mealLinks.size
|
||||||
|
@ -297,13 +295,18 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
this.menu = menu
|
||||||
inflater.inflate(R.menu.menu_treatments_carbs_bolus, menu)
|
inflater.inflate(R.menu.menu_treatments_carbs_bolus, menu)
|
||||||
super.onCreateOptionsMenu(menu, inflater)
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateMenuVisibility() {
|
||||||
|
menu?.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
||||||
|
menu?.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
||||||
|
}
|
||||||
|
|
||||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
updateMenuVisibility()
|
||||||
menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
|
||||||
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_insulin, false) || !sp.getBoolean(R.string.key_ns_receive_carbs, false) || !buildHelper.isEngineeringMode()
|
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_insulin, false) || !sp.getBoolean(R.string.key_ns_receive_carbs, false) || !buildHelper.isEngineeringMode()
|
||||||
menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly
|
menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly
|
||||||
val hasItems = (binding.recyclerview.adapter?.itemCount ?: 0) > 0
|
val hasItems = (binding.recyclerview.adapter?.itemCount ?: 0) > 0
|
||||||
|
@ -314,20 +317,21 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.nav_remove_items -> {
|
R.id.nav_remove_items -> actionHelper.startRemove()
|
||||||
removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback())
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.nav_show_invalidated -> {
|
R.id.nav_show_invalidated -> {
|
||||||
showInvalidated = true
|
showInvalidated = true
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.nav_hide_invalidated -> {
|
R.id.nav_hide_invalidated -> {
|
||||||
showInvalidated = false
|
showInvalidated = false
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.hide_invalidated_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,36 +427,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class RemoveActionModeCallback : ActionMode.Callback {
|
private fun getConfirmationText(selectedItems: SparseArray<MealLink>): String {
|
||||||
|
|
||||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
|
|
||||||
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
|
|
||||||
selectedItems.clear()
|
|
||||||
mode.title = rh.gs(R.string.count_selected, selectedItems.size())
|
|
||||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
|
|
||||||
|
|
||||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
|
||||||
return when (item.itemId) {
|
|
||||||
R.id.remove_selected -> {
|
|
||||||
removeSelected()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
|
||||||
removeActionMode = null
|
|
||||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getConfirmationText(): String {
|
|
||||||
if (selectedItems.size() == 1) {
|
if (selectedItems.size() == 1) {
|
||||||
val mealLink = selectedItems.valueAt(0)
|
val mealLink = selectedItems.valueAt(0)
|
||||||
val bolus = mealLink.bolus
|
val bolus = mealLink.bolus
|
||||||
|
@ -467,40 +442,38 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() {
|
||||||
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeSelected() {
|
private fun removeSelected(selectedItems: SparseArray<MealLink>) {
|
||||||
if (selectedItems.size() > 0)
|
activity?.let { activity ->
|
||||||
activity?.let { activity ->
|
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(selectedItems), Runnable {
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
|
selectedItems.forEach { _, ml ->
|
||||||
selectedItems.forEach { _, ml ->
|
ml.bolus?.let { bolus ->
|
||||||
ml.bolus?.let { bolus ->
|
uel.log(
|
||||||
uel.log(
|
Action.BOLUS_REMOVED, Sources.Treatments,
|
||||||
Action.BOLUS_REMOVED, Sources.Treatments,
|
ValueWithUnit.Timestamp(bolus.timestamp),
|
||||||
ValueWithUnit.Timestamp(bolus.timestamp),
|
ValueWithUnit.Insulin(bolus.amount)
|
||||||
ValueWithUnit.Insulin(bolus.amount)
|
)
|
||||||
|
disposable += repository.runTransactionForResult(InvalidateBolusTransaction(bolus.id))
|
||||||
|
.subscribe(
|
||||||
|
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bolus $it") } },
|
||||||
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating bolus", it) }
|
||||||
)
|
)
|
||||||
disposable += repository.runTransactionForResult(InvalidateBolusTransaction(bolus.id))
|
|
||||||
.subscribe(
|
|
||||||
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bolus $it") } },
|
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating bolus", it) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ml.carbs?.let { carb ->
|
|
||||||
uel.log(
|
|
||||||
Action.CARBS_REMOVED, Sources.Treatments,
|
|
||||||
ValueWithUnit.Timestamp(carb.timestamp),
|
|
||||||
ValueWithUnit.Gram(carb.amount.toInt())
|
|
||||||
)
|
|
||||||
disposable += repository.runTransactionForResult(InvalidateCarbsTransaction(carb.id))
|
|
||||||
.subscribe(
|
|
||||||
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") } },
|
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
removeActionMode?.finish()
|
ml.carbs?.let { carb ->
|
||||||
})
|
uel.log(
|
||||||
}
|
Action.CARBS_REMOVED, Sources.Treatments,
|
||||||
else
|
ValueWithUnit.Timestamp(carb.timestamp),
|
||||||
removeActionMode?.finish()
|
ValueWithUnit.Gram(carb.amount.toInt())
|
||||||
|
)
|
||||||
|
disposable += repository.runTransactionForResult(InvalidateCarbsTransaction(carb.id))
|
||||||
|
.subscribe(
|
||||||
|
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") } },
|
||||||
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
actionHelper.finish()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,39 +3,33 @@ package info.nightscout.androidaps.activities.fragments
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.ActionMode
|
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.util.forEach
|
import androidx.core.util.forEach
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.activities.fragments.TreatmentsCareportalFragment.RecyclerViewAdapter.TherapyEventsViewHolder
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.database.entities.ValueWithUnit
|
|
||||||
import info.nightscout.androidaps.database.entities.TherapyEvent
|
import info.nightscout.androidaps.database.entities.TherapyEvent
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
||||||
|
import info.nightscout.androidaps.database.entities.ValueWithUnit
|
||||||
import info.nightscout.androidaps.database.transactions.InvalidateAAPSStartedTherapyEventTransaction
|
import info.nightscout.androidaps.database.transactions.InvalidateAAPSStartedTherapyEventTransaction
|
||||||
import info.nightscout.androidaps.database.transactions.InvalidateTherapyEventTransaction
|
import info.nightscout.androidaps.database.transactions.InvalidateTherapyEventTransaction
|
||||||
import info.nightscout.androidaps.databinding.TreatmentsCareportalFragmentBinding
|
import info.nightscout.androidaps.databinding.TreatmentsCareportalFragmentBinding
|
||||||
import info.nightscout.androidaps.databinding.TreatmentsCareportalItemBinding
|
import info.nightscout.androidaps.databinding.TreatmentsCareportalItemBinding
|
||||||
import info.nightscout.androidaps.events.EventTherapyEventChange
|
import info.nightscout.androidaps.events.EventTherapyEventChange
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
|
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
|
||||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
import info.nightscout.androidaps.utils.*
|
||||||
import info.nightscout.androidaps.activities.fragments.TreatmentsCareportalFragment.RecyclerViewAdapter.TherapyEventsViewHolder
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
|
||||||
import info.nightscout.androidaps.utils.T
|
|
||||||
import info.nightscout.androidaps.utils.Translator
|
|
||||||
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
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import io.reactivex.rxjava3.core.Completable
|
import io.reactivex.rxjava3.core.Completable
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
@ -59,26 +53,28 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
|
|
||||||
private var _binding: TreatmentsCareportalFragmentBinding? = null
|
private var _binding: TreatmentsCareportalFragmentBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and onDestroyView.
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
private var menu: Menu? = null
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
private val millsToThePast = T.days(30).msecs()
|
private val millsToThePast = T.days(30).msecs()
|
||||||
private var selectedItems: SparseArray<TherapyEvent> = SparseArray()
|
private lateinit var actionHelper: ActionModeHelper<TherapyEvent>
|
||||||
private var showInvalidated = false
|
private var showInvalidated = false
|
||||||
private var toolbar: Toolbar? = null
|
|
||||||
private var removeActionMode: ActionMode? = null
|
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||||
TreatmentsCareportalFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
TreatmentsCareportalFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
toolbar = activity?.findViewById(R.id.toolbar)
|
actionHelper = ActionModeHelper(rh, activity)
|
||||||
|
actionHelper.setUpdateListHandler { binding.recyclerview.adapter?.notifyDataSetChanged() }
|
||||||
|
actionHelper.setOnRemoveHandler { removeSelected(it) }
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
|
binding.recyclerview.emptyView = binding.noRecordsText
|
||||||
|
binding.recyclerview.loadingView = binding.progressBar
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshFromNightscout() {
|
private fun refreshFromNightscout() {
|
||||||
|
@ -111,6 +107,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
||||||
|
|
||||||
fun swapAdapter() {
|
fun swapAdapter() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
|
binding.recyclerview.isLoading = true
|
||||||
disposable +=
|
disposable +=
|
||||||
if (showInvalidated)
|
if (showInvalidated)
|
||||||
repository
|
repository
|
||||||
|
@ -133,23 +130,18 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
.debounce(1L, TimeUnit.SECONDS)
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
|
actionHelper.finish()
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
removeActionMode?.let { it.finish() }
|
|
||||||
binding.recyclerview.adapter = null // avoid leaks
|
binding.recyclerview.adapter = null // avoid leaks
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
@ -165,27 +157,24 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
||||||
val therapyEvent = therapyList[position]
|
val therapyEvent = therapyList[position]
|
||||||
holder.binding.ns.visibility = (therapyEvent.interfaceIDs.nightscoutId != null).toVisibility()
|
holder.binding.ns.visibility = (therapyEvent.interfaceIDs.nightscoutId != null).toVisibility()
|
||||||
holder.binding.invalid.visibility = therapyEvent.isValid.not().toVisibility()
|
holder.binding.invalid.visibility = therapyEvent.isValid.not().toVisibility()
|
||||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(therapyEvent.timestamp, therapyList[position - 1].timestamp)
|
val newDay = position == 0 || !dateUtil.isSameDayGroup(therapyEvent.timestamp, therapyList[position - 1].timestamp)
|
||||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
holder.binding.date.visibility = newDay.toVisibility()
|
||||||
holder.binding.date.text = dateUtil.dateString(therapyEvent.timestamp)
|
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(therapyEvent.timestamp, rh) else ""
|
||||||
holder.binding.time.text = dateUtil.timeString(therapyEvent.timestamp)
|
holder.binding.time.text = dateUtil.timeString(therapyEvent.timestamp)
|
||||||
holder.binding.duration.text = if (therapyEvent.duration == 0L) "" else dateUtil.niceTimeScalar(therapyEvent.duration, rh)
|
holder.binding.duration.text = if (therapyEvent.duration == 0L) "" else dateUtil.niceTimeScalar(therapyEvent.duration, rh)
|
||||||
holder.binding.note.text = therapyEvent.note
|
holder.binding.note.text = therapyEvent.note
|
||||||
holder.binding.type.text = translator.translate(therapyEvent.type)
|
holder.binding.type.text = translator.translate(therapyEvent.type)
|
||||||
holder.binding.cbRemove.visibility = (therapyEvent.isValid && removeActionMode != null).toVisibility()
|
holder.binding.cbRemove.visibility = (therapyEvent.isValid && actionHelper.isRemoving).toVisibility()
|
||||||
if (removeActionMode != null) {
|
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
||||||
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
actionHelper.updateSelection(position, therapyEvent, value)
|
||||||
if (value) {
|
|
||||||
selectedItems.put(position, therapyEvent)
|
|
||||||
} else {
|
|
||||||
selectedItems.remove(position)
|
|
||||||
}
|
|
||||||
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
|
|
||||||
}
|
|
||||||
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
|
||||||
}
|
}
|
||||||
|
holder.binding.root.setOnClickListener {
|
||||||
|
holder.binding.cbRemove.toggle()
|
||||||
|
actionHelper.updateSelection(position, therapyEvent, holder.binding.cbRemove.isChecked)
|
||||||
|
}
|
||||||
|
holder.binding.cbRemove.isChecked = actionHelper.isSelected(position)
|
||||||
val nextTimestamp = if (therapyList.size != position + 1) therapyList[position + 1].timestamp else 0L
|
val nextTimestamp = if (therapyList.size != position + 1) therapyList[position + 1].timestamp else 0L
|
||||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(therapyEvent.timestamp, nextTimestamp).toVisibility()
|
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(therapyEvent.timestamp, nextTimestamp).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount() = therapyList.size
|
override fun getItemCount() = therapyList.size
|
||||||
|
@ -198,35 +187,41 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
this.menu = menu
|
||||||
inflater.inflate(R.menu.menu_treatments_careportal, menu)
|
inflater.inflate(R.menu.menu_treatments_careportal, menu)
|
||||||
super.onCreateOptionsMenu(menu, inflater)
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
updateMenuVisibility()
|
||||||
menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
|
||||||
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_therapy_events, false) || !buildHelper.isEngineeringMode()
|
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_therapy_events, false) || !buildHelper.isEngineeringMode()
|
||||||
menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly
|
menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly
|
||||||
|
|
||||||
return super.onPrepareOptionsMenu(menu)
|
return super.onPrepareOptionsMenu(menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateMenuVisibility() {
|
||||||
|
menu?.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
||||||
|
menu?.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
||||||
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.nav_remove_items -> {
|
R.id.nav_remove_items -> actionHelper.startRemove()
|
||||||
removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback())
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.nav_show_invalidated -> {
|
R.id.nav_show_invalidated -> {
|
||||||
showInvalidated = true
|
showInvalidated = true
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.nav_hide_invalidated -> {
|
R.id.nav_hide_invalidated -> {
|
||||||
showInvalidated = false
|
showInvalidated = false
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.hide_invalidated_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,36 +238,7 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class RemoveActionModeCallback : ActionMode.Callback {
|
private fun getConfirmationText(selectedItems: SparseArray<TherapyEvent>): String {
|
||||||
|
|
||||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
|
|
||||||
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
|
|
||||||
selectedItems.clear()
|
|
||||||
mode.title = rh.gs(R.string.count_selected, selectedItems.size())
|
|
||||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
|
|
||||||
|
|
||||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
|
||||||
return when (item.itemId) {
|
|
||||||
R.id.remove_selected -> {
|
|
||||||
removeSelected()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
|
||||||
removeActionMode = null
|
|
||||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getConfirmationText(): String {
|
|
||||||
if (selectedItems.size() == 1) {
|
if (selectedItems.size() == 1) {
|
||||||
val therapyEvent = selectedItems.valueAt(0)
|
val therapyEvent = selectedItems.valueAt(0)
|
||||||
return rh.gs(R.string.eventtype) + ": " + translator.translate(therapyEvent.type) + "\n" +
|
return rh.gs(R.string.eventtype) + ": " + translator.translate(therapyEvent.type) + "\n" +
|
||||||
|
@ -282,27 +248,24 @@ class TreatmentsCareportalFragment : DaggerFragment() {
|
||||||
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeSelected() {
|
private fun removeSelected(selectedItems: SparseArray<TherapyEvent>) {
|
||||||
if (selectedItems.size() > 0)
|
activity?.let { activity ->
|
||||||
activity?.let { activity ->
|
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(selectedItems), Runnable {
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
|
selectedItems.forEach { _, therapyEvent ->
|
||||||
selectedItems.forEach { _, therapyEvent ->
|
uel.log(
|
||||||
uel.log(
|
Action.CAREPORTAL_REMOVED, Sources.Treatments, therapyEvent.note,
|
||||||
Action.CAREPORTAL_REMOVED, Sources.Treatments, therapyEvent.note,
|
ValueWithUnit.Timestamp(therapyEvent.timestamp),
|
||||||
ValueWithUnit.Timestamp(therapyEvent.timestamp),
|
ValueWithUnit.TherapyEventType(therapyEvent.type)
|
||||||
ValueWithUnit.TherapyEventType(therapyEvent.type)
|
)
|
||||||
|
disposable += repository.runTransactionForResult(InvalidateTherapyEventTransaction(therapyEvent.id))
|
||||||
|
.subscribe(
|
||||||
|
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated therapy event $it") } },
|
||||||
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) }
|
||||||
)
|
)
|
||||||
disposable += repository.runTransactionForResult(InvalidateTherapyEventTransaction(therapyEvent.id))
|
}
|
||||||
.subscribe(
|
actionHelper.finish()
|
||||||
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated therapy event $it") } },
|
})
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) }
|
}
|
||||||
)
|
|
||||||
}
|
|
||||||
removeActionMode?.finish()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
else
|
|
||||||
removeActionMode?.finish()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,12 @@ import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.ActionMode
|
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.util.forEach
|
import androidx.core.util.forEach
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.activities.fragments.TreatmentsExtendedBolusesFragment.RecyclerViewAdapter.ExtendedBolusesViewHolder
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.database.entities.ExtendedBolus
|
import info.nightscout.androidaps.database.entities.ExtendedBolus
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
||||||
|
@ -26,20 +25,20 @@ import info.nightscout.androidaps.extensions.isInProgress
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.activities.fragments.TreatmentsExtendedBolusesFragment.RecyclerViewAdapter.ExtendedBolusesViewHolder
|
import info.nightscout.androidaps.utils.ActionModeHelper
|
||||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
|
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.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ -61,26 +60,32 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
|
|
||||||
private var _binding: TreatmentsExtendedbolusFragmentBinding? = null
|
private var _binding: TreatmentsExtendedbolusFragmentBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and onDestroyView.
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
private var menu: Menu? = null
|
||||||
private var selectedItems: SparseArray<ExtendedBolus> = SparseArray()
|
private lateinit var actionHelper: ActionModeHelper<ExtendedBolus>
|
||||||
private var showInvalidated = false
|
private var showInvalidated = false
|
||||||
private var removeActionMode: ActionMode? = null
|
|
||||||
private var toolbar: Toolbar? = null
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||||
TreatmentsExtendedbolusFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
TreatmentsExtendedbolusFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
actionHelper = ActionModeHelper(rh, activity)
|
||||||
|
actionHelper.setUpdateListHandler { binding.recyclerview.adapter?.notifyDataSetChanged() }
|
||||||
|
actionHelper.setOnRemoveHandler { removeSelected(it) }
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
toolbar = activity?.findViewById(R.id.toolbar)
|
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
|
binding.recyclerview.emptyView = binding.noRecordsText
|
||||||
|
binding.recyclerview.loadingView = binding.progressBar
|
||||||
}
|
}
|
||||||
|
|
||||||
fun swapAdapter() {
|
fun swapAdapter() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
|
binding.recyclerview.isLoading = true
|
||||||
disposable += if (showInvalidated)
|
disposable += if (showInvalidated)
|
||||||
repository
|
repository
|
||||||
.getExtendedBolusDataIncludingInvalidFromTime(now - millsToThePast, false)
|
.getExtendedBolusDataIncludingInvalidFromTime(now - millsToThePast, false)
|
||||||
|
@ -97,7 +102,6 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
swapAdapter()
|
swapAdapter()
|
||||||
|
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventExtendedBolusChange::class.java)
|
.toObservable(EventExtendedBolusChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
|
@ -108,13 +112,13 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
|
actionHelper.finish()
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
removeActionMode?.let { it.finish() }
|
|
||||||
binding.recyclerview.adapter = null // avoid leaks
|
binding.recyclerview.adapter = null // avoid leaks
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
@ -131,13 +135,12 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
||||||
holder.binding.ns.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility()
|
holder.binding.ns.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility()
|
||||||
holder.binding.ph.visibility = (extendedBolus.interfaceIDs.pumpId != null).toVisibility()
|
holder.binding.ph.visibility = (extendedBolus.interfaceIDs.pumpId != null).toVisibility()
|
||||||
holder.binding.invalid.visibility = extendedBolus.isValid.not().toVisibility()
|
holder.binding.invalid.visibility = extendedBolus.isValid.not().toVisibility()
|
||||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(extendedBolus.timestamp, extendedBolusList[position - 1].timestamp)
|
val newDay = position == 0 || !dateUtil.isSameDayGroup(extendedBolus.timestamp, extendedBolusList[position - 1].timestamp)
|
||||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
holder.binding.date.visibility = newDay.toVisibility()
|
||||||
holder.binding.date.text = dateUtil.dateString(extendedBolus.timestamp)
|
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(extendedBolus.timestamp, rh) else ""
|
||||||
@SuppressLint("SetTextI18n")
|
|
||||||
if (extendedBolus.isInProgress(dateUtil)) {
|
if (extendedBolus.isInProgress(dateUtil)) {
|
||||||
holder.binding.time.text = dateUtil.timeString(extendedBolus.timestamp)
|
holder.binding.time.text = dateUtil.timeString(extendedBolus.timestamp)
|
||||||
holder.binding.time.setTextColor(rh.gc(R.color.colorActive))
|
holder.binding.time.setTextColor(rh.gac(context , R.attr.activeColor))
|
||||||
} else {
|
} else {
|
||||||
holder.binding.time.text = dateUtil.timeRangeString(extendedBolus.timestamp, extendedBolus.end)
|
holder.binding.time.text = dateUtil.timeRangeString(extendedBolus.timestamp, extendedBolus.end)
|
||||||
holder.binding.time.setTextColor(holder.binding.insulin.currentTextColor)
|
holder.binding.time.setTextColor(holder.binding.insulin.currentTextColor)
|
||||||
|
@ -148,21 +151,20 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
||||||
val iob = extendedBolus.iobCalc(System.currentTimeMillis(), profile, activePlugin.activeInsulin)
|
val iob = extendedBolus.iobCalc(System.currentTimeMillis(), profile, activePlugin.activeInsulin)
|
||||||
holder.binding.iob.text = rh.gs(R.string.formatinsulinunits, iob.iob)
|
holder.binding.iob.text = rh.gs(R.string.formatinsulinunits, iob.iob)
|
||||||
holder.binding.ratio.text = rh.gs(R.string.pump_basebasalrate, extendedBolus.rate)
|
holder.binding.ratio.text = rh.gs(R.string.pump_basebasalrate, extendedBolus.rate)
|
||||||
if (iob.iob != 0.0) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.insulin.currentTextColor)
|
if (iob.iob != 0.0) holder.binding.iob.setTextColor(rh.gac(context , R.attr.activeColor)) else holder.binding.iob.setTextColor(holder.binding.insulin.currentTextColor)
|
||||||
holder.binding.cbRemove.visibility = (extendedBolus.isValid && removeActionMode != null).toVisibility()
|
holder.binding.cbRemove.visibility = (extendedBolus.isValid && actionHelper.isRemoving).toVisibility()
|
||||||
if (removeActionMode != null) {
|
if (actionHelper.isRemoving) {
|
||||||
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
||||||
if (value) {
|
actionHelper.updateSelection(position, extendedBolus, value)
|
||||||
selectedItems.put(position, extendedBolus)
|
|
||||||
} else {
|
|
||||||
selectedItems.remove(position)
|
|
||||||
}
|
|
||||||
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
|
|
||||||
}
|
}
|
||||||
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
holder.binding.root.setOnClickListener {
|
||||||
|
holder.binding.cbRemove.toggle()
|
||||||
|
actionHelper.updateSelection(position, extendedBolus, holder.binding.cbRemove.isChecked)
|
||||||
|
}
|
||||||
|
holder.binding.cbRemove.isChecked = actionHelper.isSelected(position)
|
||||||
}
|
}
|
||||||
val nextTimestamp = if (extendedBolusList.size != position + 1) extendedBolusList[position + 1].timestamp else 0L
|
val nextTimestamp = if (extendedBolusList.size != position + 1) extendedBolusList[position + 1].timestamp else 0L
|
||||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(extendedBolus.timestamp, nextTimestamp).toVisibility()
|
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(extendedBolus.timestamp, nextTimestamp).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount() = extendedBolusList.size
|
override fun getItemCount() = extendedBolusList.size
|
||||||
|
@ -175,33 +177,38 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
this.menu = menu
|
||||||
inflater.inflate(R.menu.menu_treatments_extended_bolus, menu)
|
inflater.inflate(R.menu.menu_treatments_extended_bolus, menu)
|
||||||
super.onCreateOptionsMenu(menu, inflater)
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
private fun updateMenuVisibility() {
|
||||||
menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
menu?.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
||||||
menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
menu?.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
|
updateMenuVisibility()
|
||||||
return super.onPrepareOptionsMenu(menu)
|
return super.onPrepareOptionsMenu(menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
return when (item.itemId) {
|
return when (item.itemId) {
|
||||||
R.id.nav_remove_items -> {
|
R.id.nav_remove_items -> actionHelper.startRemove()
|
||||||
removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback())
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.nav_show_invalidated -> {
|
R.id.nav_show_invalidated -> {
|
||||||
showInvalidated = true
|
showInvalidated = true
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.nav_hide_invalidated -> {
|
R.id.nav_hide_invalidated -> {
|
||||||
showInvalidated = false
|
showInvalidated = false
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.hide_invalidated_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,36 +216,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class RemoveActionModeCallback : ActionMode.Callback {
|
private fun getConfirmationText(selectedItems: SparseArray<ExtendedBolus>): String {
|
||||||
|
|
||||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
|
|
||||||
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
|
|
||||||
selectedItems.clear()
|
|
||||||
mode.title = rh.gs(R.string.count_selected, selectedItems.size())
|
|
||||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
|
|
||||||
|
|
||||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
|
||||||
return when (item.itemId) {
|
|
||||||
R.id.remove_selected -> {
|
|
||||||
removeSelected()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
|
||||||
removeActionMode = null
|
|
||||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getConfirmationText(): String {
|
|
||||||
if (selectedItems.size() == 1) {
|
if (selectedItems.size() == 1) {
|
||||||
val bolus = selectedItems.valueAt(0)
|
val bolus = selectedItems.valueAt(0)
|
||||||
return rh.gs(R.string.extended_bolus) + "\n" +
|
return rh.gs(R.string.extended_bolus) + "\n" +
|
||||||
|
@ -247,27 +225,25 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() {
|
||||||
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeSelected() {
|
private fun removeSelected(selectedItems: SparseArray<ExtendedBolus>) {
|
||||||
if (selectedItems.size() > 0)
|
activity?.let { activity ->
|
||||||
activity?.let { activity ->
|
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(selectedItems), Runnable {
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
|
selectedItems.forEach { _, extendedBolus ->
|
||||||
selectedItems.forEach { _, extendedBolus ->
|
uel.log(
|
||||||
uel.log(
|
Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments,
|
||||||
Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments,
|
ValueWithUnit.Timestamp(extendedBolus.timestamp),
|
||||||
ValueWithUnit.Timestamp(extendedBolus.timestamp),
|
ValueWithUnit.Insulin(extendedBolus.amount),
|
||||||
ValueWithUnit.Insulin(extendedBolus.amount),
|
ValueWithUnit.UnitPerHour(extendedBolus.rate),
|
||||||
ValueWithUnit.UnitPerHour(extendedBolus.rate),
|
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt())
|
||||||
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt())
|
)
|
||||||
)
|
disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id))
|
||||||
disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id))
|
.subscribe(
|
||||||
.subscribe(
|
{ aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") },
|
||||||
{ aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") },
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) })
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) })
|
}
|
||||||
}
|
actionHelper.finish()
|
||||||
removeActionMode?.finish()
|
})
|
||||||
})
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
removeActionMode?.finish()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package info.nightscout.androidaps.activities.fragments
|
package info.nightscout.androidaps.activities.fragments
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.ActionMode
|
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.util.forEach
|
import androidx.core.util.forEach
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
@ -23,7 +22,6 @@ import info.nightscout.androidaps.databinding.TreatmentsProfileswitchItemBinding
|
||||||
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
|
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
|
||||||
import info.nightscout.androidaps.events.EventEffectiveProfileSwitchChanged
|
import info.nightscout.androidaps.events.EventEffectiveProfileSwitchChanged
|
||||||
import info.nightscout.androidaps.events.EventProfileSwitchChanged
|
import info.nightscout.androidaps.events.EventProfileSwitchChanged
|
||||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
|
||||||
import info.nightscout.androidaps.extensions.getCustomizedName
|
import info.nightscout.androidaps.extensions.getCustomizedName
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
|
@ -32,9 +30,11 @@ import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientR
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
|
||||||
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
|
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin
|
||||||
import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged
|
import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged
|
||||||
|
import info.nightscout.androidaps.utils.ActionModeHelper
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
|
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.buildHelper.BuildHelper
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
@ -63,26 +63,29 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
|
|
||||||
private var _binding: TreatmentsProfileswitchFragmentBinding? = null
|
private var _binding: TreatmentsProfileswitchFragmentBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and onDestroyView.
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
private var menu: Menu? = null
|
||||||
|
private lateinit var actionHelper: ActionModeHelper<ProfileSealed>
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
private val millsToThePast = T.days(30).msecs()
|
private val millsToThePast = T.days(30).msecs()
|
||||||
private var selectedItems: SparseArray<ProfileSealed> = SparseArray()
|
|
||||||
private var showInvalidated = false
|
private var showInvalidated = false
|
||||||
private var removeActionMode: ActionMode? = null
|
|
||||||
private var toolbar: Toolbar? = null
|
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||||
TreatmentsProfileswitchFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
TreatmentsProfileswitchFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
actionHelper = ActionModeHelper(rh, activity)
|
||||||
|
actionHelper.setUpdateListHandler { binding.recyclerview.adapter?.notifyDataSetChanged() }
|
||||||
|
actionHelper.setOnRemoveHandler { removeSelected(it) }
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
toolbar = activity?.findViewById(R.id.toolbar)
|
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
|
binding.recyclerview.emptyView = binding.noRecordsText
|
||||||
|
binding.recyclerview.loadingView = binding.progressBar
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshFromNightscout() {
|
private fun refreshFromNightscout() {
|
||||||
|
@ -127,7 +130,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
|
|
||||||
fun swapAdapter() {
|
fun swapAdapter() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
|
binding.recyclerview.isLoading = true
|
||||||
disposable +=
|
disposable +=
|
||||||
if (showInvalidated)
|
if (showInvalidated)
|
||||||
profileSwitchWithInvalid(now)
|
profileSwitchWithInvalid(now)
|
||||||
|
@ -164,13 +167,13 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
|
actionHelper.finish()
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
removeActionMode?.finish()
|
|
||||||
binding.recyclerview.adapter = null // avoid leaks
|
binding.recyclerview.adapter = null // avoid leaks
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
@ -184,36 +187,35 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
val profileSwitch = profileSwitchList[position]
|
val profileSwitch = profileSwitchList[position]
|
||||||
holder.binding.ph.visibility = (profileSwitch is ProfileSealed.EPS).toVisibility()
|
holder.binding.ph.visibility = (profileSwitch is ProfileSealed.EPS).toVisibility()
|
||||||
holder.binding.ns.visibility = (profileSwitch.interfaceIDs_backing?.nightscoutId != null).toVisibility()
|
holder.binding.ns.visibility = (profileSwitch.interfaceIDs_backing?.nightscoutId != null).toVisibility()
|
||||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(profileSwitch.timestamp, profileSwitchList[position - 1].timestamp)
|
val newDay = position == 0 || !dateUtil.isSameDayGroup(profileSwitch.timestamp, profileSwitchList[position - 1].timestamp)
|
||||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
holder.binding.date.visibility = newDay.toVisibility()
|
||||||
holder.binding.date.text = dateUtil.dateString(profileSwitch.timestamp)
|
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(profileSwitch.timestamp, rh) else ""
|
||||||
holder.binding.time.text = dateUtil.timeString(profileSwitch.timestamp)
|
holder.binding.time.text = dateUtil.timeString(profileSwitch.timestamp)
|
||||||
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(profileSwitch.duration ?: 0L).mins())
|
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(profileSwitch.duration ?: 0L).mins())
|
||||||
holder.binding.name.text =
|
holder.binding.name.text =
|
||||||
if (profileSwitch is ProfileSealed.PS) profileSwitch.value.getCustomizedName() else if (profileSwitch is ProfileSealed.EPS) profileSwitch.value.originalCustomizedName else ""
|
if (profileSwitch is ProfileSealed.PS) profileSwitch.value.getCustomizedName() else if (profileSwitch is ProfileSealed.EPS) profileSwitch.value.originalCustomizedName else ""
|
||||||
if (profileSwitch.isInProgress(dateUtil)) holder.binding.date.setTextColor(rh.gc(R.color.colorActive))
|
if (profileSwitch.isInProgress(dateUtil)) holder.binding.date.setTextColor(rh.gac(context , R.attr.activeColor))
|
||||||
else holder.binding.date.setTextColor(holder.binding.duration.currentTextColor)
|
else holder.binding.date.setTextColor(holder.binding.duration.currentTextColor)
|
||||||
holder.binding.clone.tag = profileSwitch
|
holder.binding.clone.tag = profileSwitch
|
||||||
holder.binding.name.tag = profileSwitch
|
holder.binding.name.tag = profileSwitch
|
||||||
holder.binding.date.tag = profileSwitch
|
holder.binding.date.tag = profileSwitch
|
||||||
holder.binding.invalid.visibility = profileSwitch.isValid.not().toVisibility()
|
holder.binding.invalid.visibility = profileSwitch.isValid.not().toVisibility()
|
||||||
holder.binding.duration.visibility = (profileSwitch.duration != 0L && profileSwitch.duration != null).toVisibility()
|
holder.binding.duration.visibility = (profileSwitch.duration != 0L && profileSwitch.duration != null).toVisibility()
|
||||||
holder.binding.cbRemove.visibility = (removeActionMode != null && profileSwitch is ProfileSealed.PS).toVisibility()
|
holder.binding.cbRemove.visibility = (actionHelper.isRemoving && profileSwitch is ProfileSealed.PS).toVisibility()
|
||||||
if (removeActionMode != null) {
|
if (actionHelper.isRemoving) {
|
||||||
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
||||||
if (value) {
|
actionHelper.updateSelection(position, profileSwitch, value)
|
||||||
selectedItems.put(position, profileSwitch)
|
|
||||||
} else {
|
|
||||||
selectedItems.remove(position)
|
|
||||||
}
|
|
||||||
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
|
|
||||||
}
|
}
|
||||||
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
holder.binding.root.setOnClickListener {
|
||||||
|
holder.binding.cbRemove.toggle()
|
||||||
|
actionHelper.updateSelection(position, profileSwitch, holder.binding.cbRemove.isChecked)
|
||||||
|
}
|
||||||
|
holder.binding.cbRemove.isChecked = actionHelper.isSelected(position)
|
||||||
}
|
}
|
||||||
holder.binding.clone.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
|
holder.binding.clone.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
|
||||||
holder.binding.spacer.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
|
holder.binding.spacer.visibility = (profileSwitch is ProfileSealed.PS).toVisibility()
|
||||||
val nextTimestamp = if (profileSwitchList.size != position + 1) profileSwitchList[position + 1].timestamp else 0L
|
val nextTimestamp = if (profileSwitchList.size != position + 1) profileSwitchList[position + 1].timestamp else 0L
|
||||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(profileSwitch.timestamp, nextTimestamp).toVisibility()
|
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(profileSwitch.timestamp, nextTimestamp).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount() = profileSwitchList.size
|
override fun getItemCount() = profileSwitchList.size
|
||||||
|
@ -273,13 +275,18 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
this.menu = menu
|
||||||
inflater.inflate(R.menu.menu_treatments_profile_switch, menu)
|
inflater.inflate(R.menu.menu_treatments_profile_switch, menu)
|
||||||
super.onCreateOptionsMenu(menu, inflater)
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateMenuVisibility() {
|
||||||
|
menu?.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
||||||
|
menu?.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
||||||
|
}
|
||||||
|
|
||||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
updateMenuVisibility()
|
||||||
menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
|
||||||
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_profile_switch, false) || !buildHelper.isEngineeringMode()
|
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_profile_switch, false) || !buildHelper.isEngineeringMode()
|
||||||
menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly
|
menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly
|
||||||
|
|
||||||
|
@ -288,20 +295,21 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.nav_remove_items -> {
|
R.id.nav_remove_items -> actionHelper.startRemove()
|
||||||
removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback())
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.nav_show_invalidated -> {
|
R.id.nav_show_invalidated -> {
|
||||||
showInvalidated = true
|
showInvalidated = true
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.nav_hide_invalidated -> {
|
R.id.nav_hide_invalidated -> {
|
||||||
showInvalidated = false
|
showInvalidated = false
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.hide_invalidated_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,36 +321,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class RemoveActionModeCallback : ActionMode.Callback {
|
private fun getConfirmationText(selectedItems: SparseArray<ProfileSealed>): String {
|
||||||
|
|
||||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
|
|
||||||
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
|
|
||||||
selectedItems.clear()
|
|
||||||
mode.title = rh.gs(R.string.count_selected, selectedItems.size())
|
|
||||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
|
|
||||||
|
|
||||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
|
||||||
return when (item.itemId) {
|
|
||||||
R.id.remove_selected -> {
|
|
||||||
removeSelected()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
|
||||||
removeActionMode = null
|
|
||||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getConfirmationText(): String {
|
|
||||||
if (selectedItems.size() == 1) {
|
if (selectedItems.size() == 1) {
|
||||||
val profileSwitch = selectedItems.valueAt(0)
|
val profileSwitch = selectedItems.valueAt(0)
|
||||||
return rh.gs(R.string.careportal_profileswitch) + ": " + profileSwitch.profileName + "\n" + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(profileSwitch.timestamp)
|
return rh.gs(R.string.careportal_profileswitch) + ": " + profileSwitch.profileName + "\n" + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(profileSwitch.timestamp)
|
||||||
|
@ -350,25 +329,22 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() {
|
||||||
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeSelected() {
|
private fun removeSelected(selectedItems: SparseArray<ProfileSealed>) {
|
||||||
if (selectedItems.size() > 0)
|
activity?.let { activity ->
|
||||||
activity?.let { activity ->
|
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(selectedItems), Runnable {
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
|
selectedItems.forEach { _, profileSwitch ->
|
||||||
selectedItems.forEach { _, profileSwitch ->
|
uel.log(
|
||||||
uel.log(
|
Action.PROFILE_SWITCH_REMOVED, Sources.Treatments, profileSwitch.profileName,
|
||||||
Action.PROFILE_SWITCH_REMOVED, Sources.Treatments, profileSwitch.profileName,
|
ValueWithUnit.Timestamp(profileSwitch.timestamp)
|
||||||
ValueWithUnit.Timestamp(profileSwitch.timestamp)
|
)
|
||||||
|
disposable += repository.runTransactionForResult(InvalidateProfileSwitchTransaction(profileSwitch.id))
|
||||||
|
.subscribe(
|
||||||
|
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated ProfileSwitch $it") } },
|
||||||
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it) }
|
||||||
)
|
)
|
||||||
disposable += repository.runTransactionForResult(InvalidateProfileSwitchTransaction(profileSwitch.id))
|
}
|
||||||
.subscribe(
|
actionHelper.finish()
|
||||||
{ result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated ProfileSwitch $it") } },
|
})
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it) }
|
}
|
||||||
)
|
|
||||||
}
|
|
||||||
removeActionMode?.finish()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
else
|
|
||||||
removeActionMode?.finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,46 +4,41 @@ import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.util.forEach
|
import androidx.core.util.forEach
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.activities.fragments.TreatmentsTempTargetFragment.RecyclerViewAdapter.TempTargetsViewHolder
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.database.ValueWrapper
|
import info.nightscout.androidaps.database.ValueWrapper
|
||||||
import info.nightscout.androidaps.database.entities.ValueWithUnit
|
|
||||||
import info.nightscout.androidaps.database.entities.TemporaryTarget
|
import info.nightscout.androidaps.database.entities.TemporaryTarget
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
||||||
|
import info.nightscout.androidaps.database.entities.ValueWithUnit
|
||||||
import info.nightscout.androidaps.database.interfaces.end
|
import info.nightscout.androidaps.database.interfaces.end
|
||||||
import info.nightscout.androidaps.database.transactions.InvalidateTemporaryTargetTransaction
|
import info.nightscout.androidaps.database.transactions.InvalidateTemporaryTargetTransaction
|
||||||
import info.nightscout.androidaps.databinding.TreatmentsTemptargetFragmentBinding
|
import info.nightscout.androidaps.databinding.TreatmentsTemptargetFragmentBinding
|
||||||
import info.nightscout.androidaps.databinding.TreatmentsTemptargetItemBinding
|
import info.nightscout.androidaps.databinding.TreatmentsTemptargetItemBinding
|
||||||
import info.nightscout.androidaps.events.EventTempTargetChange
|
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
|
|
||||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
|
||||||
import info.nightscout.androidaps.activities.fragments.TreatmentsTempTargetFragment.RecyclerViewAdapter.TempTargetsViewHolder
|
|
||||||
import info.nightscout.androidaps.events.EventEffectiveProfileSwitchChanged
|
import info.nightscout.androidaps.events.EventEffectiveProfileSwitchChanged
|
||||||
import info.nightscout.androidaps.events.EventProfileSwitchChanged
|
import info.nightscout.androidaps.events.EventProfileSwitchChanged
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.events.EventTempTargetChange
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
|
||||||
import info.nightscout.androidaps.utils.T
|
|
||||||
import info.nightscout.androidaps.utils.Translator
|
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
|
||||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
|
||||||
import info.nightscout.androidaps.extensions.friendlyDescription
|
import info.nightscout.androidaps.extensions.friendlyDescription
|
||||||
import info.nightscout.androidaps.extensions.highValueToUnitsToString
|
import info.nightscout.androidaps.extensions.highValueToUnitsToString
|
||||||
import info.nightscout.androidaps.extensions.lowValueToUnitsToString
|
import info.nightscout.androidaps.extensions.lowValueToUnitsToString
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
|
||||||
|
import info.nightscout.androidaps.utils.*
|
||||||
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import io.reactivex.rxjava3.core.Completable
|
import io.reactivex.rxjava3.core.Completable
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
@ -68,24 +63,28 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
|
|
||||||
private var _binding: TreatmentsTemptargetFragmentBinding? = null
|
private var _binding: TreatmentsTemptargetFragmentBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and onDestroyView.
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
private var menu: Menu? = null
|
||||||
|
private lateinit var actionHelper: ActionModeHelper<TemporaryTarget>
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
private val millsToThePast = T.days(30).msecs()
|
private val millsToThePast = T.days(30).msecs()
|
||||||
private var selectedItems: SparseArray<TemporaryTarget> = SparseArray()
|
|
||||||
private var showInvalidated = false
|
private var showInvalidated = false
|
||||||
private var toolbar: Toolbar? = null
|
|
||||||
private var removeActionMode: ActionMode? = null
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||||
TreatmentsTemptargetFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
TreatmentsTemptargetFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
toolbar = activity?.findViewById(R.id.toolbar)
|
actionHelper = ActionModeHelper(rh, activity)
|
||||||
|
actionHelper.setUpdateListHandler { binding.recyclerview.adapter?.notifyDataSetChanged() }
|
||||||
|
actionHelper.setOnRemoveHandler { removeSelected(it) }
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
|
binding.recyclerview.emptyView = binding.noRecordsText
|
||||||
|
binding.recyclerview.loadingView = binding.progressBar
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshFromNightscout() {
|
private fun refreshFromNightscout() {
|
||||||
|
@ -114,6 +113,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
||||||
|
|
||||||
fun swapAdapter() {
|
fun swapAdapter() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
|
binding.recyclerview.isLoading = true
|
||||||
disposable +=
|
disposable +=
|
||||||
if (showInvalidated)
|
if (showInvalidated)
|
||||||
repository
|
repository
|
||||||
|
@ -131,30 +131,23 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
swapAdapter()
|
swapAdapter()
|
||||||
|
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventTempTargetChange::class.java)
|
.toObservable(EventTempTargetChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
.debounce(1L, TimeUnit.SECONDS)
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||||
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventTreatmentUpdateGui::class.java) // TODO join with above
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
|
actionHelper.finish()
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
removeActionMode?.let { it.finish() }
|
|
||||||
binding.recyclerview.adapter = null // avoid leaks
|
binding.recyclerview.adapter = null // avoid leaks
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
@ -173,21 +166,20 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
||||||
val tempTarget = tempTargetList[position]
|
val tempTarget = tempTargetList[position]
|
||||||
holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility()
|
holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility()
|
||||||
holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility()
|
holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility()
|
||||||
holder.binding.cbRemove.visibility = (tempTarget.isValid && removeActionMode != null).toVisibility()
|
holder.binding.cbRemove.visibility = (tempTarget.isValid && actionHelper.isRemoving).toVisibility()
|
||||||
if (removeActionMode != null) {
|
if (actionHelper.isRemoving) {
|
||||||
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
||||||
if (value) {
|
actionHelper.updateSelection(position, tempTarget, value)
|
||||||
selectedItems.put(position, tempTarget)
|
|
||||||
} else {
|
|
||||||
selectedItems.remove(position)
|
|
||||||
}
|
|
||||||
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
|
|
||||||
}
|
}
|
||||||
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
holder.binding.root.setOnClickListener {
|
||||||
|
holder.binding.cbRemove.toggle()
|
||||||
|
actionHelper.updateSelection(position, tempTarget, holder.binding.cbRemove.isChecked)
|
||||||
|
}
|
||||||
|
holder.binding.cbRemove.isChecked = actionHelper.isSelected(position)
|
||||||
}
|
}
|
||||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempTarget.timestamp, tempTargetList[position - 1].timestamp)
|
val newDay = position == 0 || !dateUtil.isSameDayGroup(tempTarget.timestamp, tempTargetList[position - 1].timestamp)
|
||||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
holder.binding.date.visibility = newDay.toVisibility()
|
||||||
holder.binding.date.text = dateUtil.dateString(tempTarget.timestamp)
|
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(tempTarget.timestamp, rh) else ""
|
||||||
holder.binding.time.text = dateUtil.timeRangeString(tempTarget.timestamp, tempTarget.end)
|
holder.binding.time.text = dateUtil.timeRangeString(tempTarget.timestamp, tempTarget.end)
|
||||||
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(tempTarget.duration).mins())
|
holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(tempTarget.duration).mins())
|
||||||
holder.binding.low.text = tempTarget.lowValueToUnitsToString(units)
|
holder.binding.low.text = tempTarget.lowValueToUnitsToString(units)
|
||||||
|
@ -195,13 +187,13 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
||||||
holder.binding.reason.text = translator.translate(tempTarget.reason)
|
holder.binding.reason.text = translator.translate(tempTarget.reason)
|
||||||
holder.binding.time.setTextColor(
|
holder.binding.time.setTextColor(
|
||||||
when {
|
when {
|
||||||
tempTarget.id == currentlyActiveTarget?.id -> rh.gc(R.color.colorActive)
|
tempTarget.id == currentlyActiveTarget?.id -> rh.gac(context , R.attr.activeColor)
|
||||||
tempTarget.timestamp > dateUtil.now() -> rh.gc(R.color.colorScheduled)
|
tempTarget.timestamp > dateUtil.now() -> rh.gac(context , R.attr.scheduledColor)
|
||||||
else -> holder.binding.reasonColon.currentTextColor
|
else -> holder.binding.reasonColon.currentTextColor
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
val nextTimestamp = if (tempTargetList.size != position + 1) tempTargetList[position + 1].timestamp else 0L
|
val nextTimestamp = if (tempTargetList.size != position + 1) tempTargetList[position + 1].timestamp else 0L
|
||||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(tempTarget.timestamp, nextTimestamp).toVisibility()
|
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(tempTarget.timestamp, nextTimestamp).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount() = tempTargetList.size
|
override fun getItemCount() = tempTargetList.size
|
||||||
|
@ -213,39 +205,19 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeSelected() {
|
|
||||||
if (selectedItems.size() > 0)
|
|
||||||
activity?.let { activity ->
|
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
|
|
||||||
selectedItems.forEach { _, tempTarget ->
|
|
||||||
uel.log(
|
|
||||||
Action.TT_REMOVED, Sources.Treatments,
|
|
||||||
ValueWithUnit.Timestamp(tempTarget.timestamp),
|
|
||||||
ValueWithUnit.TherapyEventTTReason(tempTarget.reason),
|
|
||||||
ValueWithUnit.Mgdl(tempTarget.lowTarget),
|
|
||||||
ValueWithUnit.Mgdl(tempTarget.highTarget).takeIf { tempTarget.lowTarget != tempTarget.highTarget },
|
|
||||||
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tempTarget.duration).toInt())
|
|
||||||
)
|
|
||||||
disposable += repository.runTransactionForResult(InvalidateTemporaryTargetTransaction(tempTarget.id))
|
|
||||||
.subscribe(
|
|
||||||
{ aapsLogger.debug(LTag.DATABASE, "Removed temp target $tempTarget") },
|
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary target", it) })
|
|
||||||
}
|
|
||||||
removeActionMode?.finish()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
else
|
|
||||||
removeActionMode?.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
this.menu = menu
|
||||||
inflater.inflate(R.menu.menu_treatments_temp_target, menu)
|
inflater.inflate(R.menu.menu_treatments_temp_target, menu)
|
||||||
super.onCreateOptionsMenu(menu, inflater)
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateMenuVisibility() {
|
||||||
|
menu?.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
||||||
|
menu?.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
||||||
|
}
|
||||||
|
|
||||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
updateMenuVisibility()
|
||||||
menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
|
||||||
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_temp_target, false) || !buildHelper.isEngineeringMode()
|
val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_temp_target, false) || !buildHelper.isEngineeringMode()
|
||||||
menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly
|
menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly
|
||||||
|
|
||||||
|
@ -254,20 +226,21 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.nav_remove_items -> {
|
R.id.nav_remove_items -> actionHelper.startRemove()
|
||||||
removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback())
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.nav_show_invalidated -> {
|
R.id.nav_show_invalidated -> {
|
||||||
showInvalidated = true
|
showInvalidated = true
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.nav_hide_invalidated -> {
|
R.id.nav_hide_invalidated -> {
|
||||||
showInvalidated = false
|
showInvalidated = false
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,36 +252,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class RemoveActionModeCallback : ActionMode.Callback {
|
private fun getConfirmationText(selectedItems: SparseArray<TemporaryTarget>): String {
|
||||||
|
|
||||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
|
|
||||||
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
|
|
||||||
selectedItems.clear()
|
|
||||||
mode.title = rh.gs(R.string.count_selected, selectedItems.size())
|
|
||||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
|
|
||||||
|
|
||||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
|
||||||
return when (item.itemId) {
|
|
||||||
R.id.remove_selected -> {
|
|
||||||
removeSelected()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
|
||||||
removeActionMode = null
|
|
||||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getConfirmationText(): String {
|
|
||||||
if (selectedItems.size() == 1) {
|
if (selectedItems.size() == 1) {
|
||||||
val tempTarget = selectedItems.valueAt(0)
|
val tempTarget = selectedItems.valueAt(0)
|
||||||
return "${rh.gs(R.string.careportal_temporarytarget)}: ${tempTarget.friendlyDescription(profileFunction.getUnits(), rh)}\n" +
|
return "${rh.gs(R.string.careportal_temporarytarget)}: ${tempTarget.friendlyDescription(profileFunction.getUnits(), rh)}\n" +
|
||||||
|
@ -317,4 +261,26 @@ class TreatmentsTempTargetFragment : DaggerFragment() {
|
||||||
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun removeSelected(selectedItems: SparseArray<TemporaryTarget>) {
|
||||||
|
activity?.let { activity ->
|
||||||
|
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(selectedItems), Runnable {
|
||||||
|
selectedItems.forEach { _, tempTarget ->
|
||||||
|
uel.log(
|
||||||
|
Action.TT_REMOVED, Sources.Treatments,
|
||||||
|
ValueWithUnit.Timestamp(tempTarget.timestamp),
|
||||||
|
ValueWithUnit.TherapyEventTTReason(tempTarget.reason),
|
||||||
|
ValueWithUnit.Mgdl(tempTarget.lowTarget),
|
||||||
|
ValueWithUnit.Mgdl(tempTarget.highTarget).takeIf { tempTarget.lowTarget != tempTarget.highTarget },
|
||||||
|
ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tempTarget.duration).toInt())
|
||||||
|
)
|
||||||
|
disposable += repository.runTransactionForResult(InvalidateTemporaryTargetTransaction(tempTarget.id))
|
||||||
|
.subscribe(
|
||||||
|
{ aapsLogger.debug(LTag.DATABASE, "Removed temp target $tempTarget") },
|
||||||
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary target", it) })
|
||||||
|
}
|
||||||
|
actionHelper.finish()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
package info.nightscout.androidaps.activities.fragments
|
package info.nightscout.androidaps.activities.fragments
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.util.forEach
|
import androidx.core.util.forEach
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.activities.fragments.TreatmentsTemporaryBasalsFragment.RecyclerViewAdapter.TempBasalsViewHolder
|
||||||
import info.nightscout.androidaps.data.IobTotal
|
import info.nightscout.androidaps.data.IobTotal
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.database.ValueWrapper
|
import info.nightscout.androidaps.database.ValueWrapper
|
||||||
|
@ -23,7 +23,6 @@ import info.nightscout.androidaps.database.transactions.InvalidateExtendedBolusT
|
||||||
import info.nightscout.androidaps.database.transactions.InvalidateTemporaryBasalTransaction
|
import info.nightscout.androidaps.database.transactions.InvalidateTemporaryBasalTransaction
|
||||||
import info.nightscout.androidaps.databinding.TreatmentsTempbasalsFragmentBinding
|
import info.nightscout.androidaps.databinding.TreatmentsTempbasalsFragmentBinding
|
||||||
import info.nightscout.androidaps.databinding.TreatmentsTempbasalsItemBinding
|
import info.nightscout.androidaps.databinding.TreatmentsTempbasalsItemBinding
|
||||||
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
|
||||||
import info.nightscout.androidaps.events.EventTempBasalChange
|
import info.nightscout.androidaps.events.EventTempBasalChange
|
||||||
import info.nightscout.androidaps.extensions.iobCalc
|
import info.nightscout.androidaps.extensions.iobCalc
|
||||||
import info.nightscout.androidaps.extensions.toStringFull
|
import info.nightscout.androidaps.extensions.toStringFull
|
||||||
|
@ -31,18 +30,18 @@ import info.nightscout.androidaps.extensions.toTemporaryBasal
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.activities.fragments.TreatmentsTemporaryBasalsFragment.RecyclerViewAdapter.TempBasalsViewHolder
|
import info.nightscout.androidaps.utils.ActionModeHelper
|
||||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
|
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.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
@ -65,24 +64,28 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
|
|
||||||
private var _binding: TreatmentsTempbasalsFragmentBinding? = null
|
private var _binding: TreatmentsTempbasalsFragmentBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and onDestroyView.
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
private var menu: Menu? = null
|
||||||
|
private lateinit var actionHelper: ActionModeHelper<TemporaryBasal>
|
||||||
private val millsToThePast = T.days(30).msecs()
|
private val millsToThePast = T.days(30).msecs()
|
||||||
private var selectedItems: SparseArray<TemporaryBasal> = SparseArray()
|
|
||||||
private var showInvalidated = false
|
private var showInvalidated = false
|
||||||
private var toolbar: Toolbar? = null
|
|
||||||
private var removeActionMode: ActionMode? = null
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||||
TreatmentsTempbasalsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
TreatmentsTempbasalsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
toolbar = activity?.findViewById(R.id.toolbar)
|
actionHelper = ActionModeHelper(rh, activity)
|
||||||
|
actionHelper.setUpdateListHandler { binding.recyclerview.adapter?.notifyDataSetChanged() }
|
||||||
|
actionHelper.setOnRemoveHandler { removeSelected(it) }
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
|
binding.recyclerview.emptyView = binding.noRecordsText
|
||||||
|
binding.recyclerview.loadingView = binding.progressBar
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun tempBasalsWithInvalid(now: Long) = repository
|
private fun tempBasalsWithInvalid(now: Long) = repository
|
||||||
|
@ -101,6 +104,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
|
|
||||||
fun swapAdapter() {
|
fun swapAdapter() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
|
binding.recyclerview.isLoading = true
|
||||||
disposable +=
|
disposable +=
|
||||||
if (activePlugin.activePump.isFakingTempsByExtendedBoluses) {
|
if (activePlugin.activePump.isFakingTempsByExtendedBoluses) {
|
||||||
if (showInvalidated)
|
if (showInvalidated)
|
||||||
|
@ -134,28 +138,22 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
swapAdapter()
|
swapAdapter()
|
||||||
|
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventTempBasalChange::class.java)
|
.toObservable(EventTempBasalChange::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||||
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
|
actionHelper.finish()
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
removeActionMode?.let { it.finish() }
|
|
||||||
binding.recyclerview.adapter = null // avoid leaks
|
binding.recyclerview.adapter = null // avoid leaks
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
@ -172,10 +170,12 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
holder.binding.ph.visibility = (tempBasal.interfaceIDs.pumpId != null).toVisibility()
|
holder.binding.ph.visibility = (tempBasal.interfaceIDs.pumpId != null).toVisibility()
|
||||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempBasal.timestamp, tempBasalList[position - 1].timestamp)
|
val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempBasal.timestamp, tempBasalList[position - 1].timestamp)
|
||||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
||||||
holder.binding.date.text = dateUtil.dateString(tempBasal.timestamp)
|
val newDay = position == 0 || !dateUtil.isSameDayGroup(tempBasal.timestamp, tempBasalList[position - 1].timestamp)
|
||||||
|
holder.binding.date.visibility = newDay.toVisibility()
|
||||||
|
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(tempBasal.timestamp, rh) else ""
|
||||||
if (tempBasal.isInProgress) {
|
if (tempBasal.isInProgress) {
|
||||||
holder.binding.time.text = dateUtil.timeString(tempBasal.timestamp)
|
holder.binding.time.text = dateUtil.timeString(tempBasal.timestamp)
|
||||||
holder.binding.time.setTextColor(rh.gc(R.color.colorActive))
|
holder.binding.time.setTextColor(rh.gac(context, R.attr.activeColor))
|
||||||
} else {
|
} else {
|
||||||
holder.binding.time.text = dateUtil.timeRangeString(tempBasal.timestamp, tempBasal.end)
|
holder.binding.time.text = dateUtil.timeRangeString(tempBasal.timestamp, tempBasal.end)
|
||||||
holder.binding.time.setTextColor(holder.binding.duration.currentTextColor)
|
holder.binding.time.setTextColor(holder.binding.duration.currentTextColor)
|
||||||
|
@ -192,21 +192,20 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
holder.binding.suspendFlag.visibility = (tempBasal.type == TemporaryBasal.Type.PUMP_SUSPEND).toVisibility()
|
holder.binding.suspendFlag.visibility = (tempBasal.type == TemporaryBasal.Type.PUMP_SUSPEND).toVisibility()
|
||||||
holder.binding.emulatedSuspendFlag.visibility = (tempBasal.type == TemporaryBasal.Type.EMULATED_PUMP_SUSPEND).toVisibility()
|
holder.binding.emulatedSuspendFlag.visibility = (tempBasal.type == TemporaryBasal.Type.EMULATED_PUMP_SUSPEND).toVisibility()
|
||||||
holder.binding.superBolusFlag.visibility = (tempBasal.type == TemporaryBasal.Type.SUPERBOLUS).toVisibility()
|
holder.binding.superBolusFlag.visibility = (tempBasal.type == TemporaryBasal.Type.SUPERBOLUS).toVisibility()
|
||||||
if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor)
|
if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(rh.gac(context, R.attr.activeColor)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor)
|
||||||
holder.binding.cbRemove.visibility = (tempBasal.isValid && removeActionMode != null).toVisibility()
|
holder.binding.cbRemove.visibility = (tempBasal.isValid && actionHelper.isRemoving).toVisibility()
|
||||||
if (removeActionMode != null) {
|
if (actionHelper.isRemoving) {
|
||||||
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
||||||
if (value) {
|
actionHelper.updateSelection(position, tempBasal, value)
|
||||||
selectedItems.put(position, tempBasal)
|
|
||||||
} else {
|
|
||||||
selectedItems.remove(position)
|
|
||||||
}
|
|
||||||
removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size())
|
|
||||||
}
|
}
|
||||||
holder.binding.cbRemove.isChecked = selectedItems.get(position) != null
|
holder.binding.root.setOnClickListener {
|
||||||
|
holder.binding.cbRemove.toggle()
|
||||||
|
actionHelper.updateSelection(position, tempBasal, holder.binding.cbRemove.isChecked)
|
||||||
|
}
|
||||||
|
holder.binding.cbRemove.isChecked = actionHelper.isSelected(position)
|
||||||
}
|
}
|
||||||
val nextTimestamp = if (tempBasalList.size != position + 1) tempBasalList[position + 1].timestamp else 0L
|
val nextTimestamp = if (tempBasalList.size != position + 1) tempBasalList[position + 1].timestamp else 0L
|
||||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(tempBasal.timestamp, nextTimestamp).toVisibility()
|
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(tempBasal.timestamp, nextTimestamp).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount() = tempBasalList.size
|
override fun getItemCount() = tempBasalList.size
|
||||||
|
@ -220,69 +219,46 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
this.menu = menu
|
||||||
inflater.inflate(R.menu.menu_treatments_temp_basal, menu)
|
inflater.inflate(R.menu.menu_treatments_temp_basal, menu)
|
||||||
super.onCreateOptionsMenu(menu, inflater)
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateMenuVisibility() {
|
||||||
|
menu?.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
||||||
|
menu?.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
||||||
|
}
|
||||||
|
|
||||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated
|
updateMenuVisibility()
|
||||||
menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated
|
|
||||||
|
|
||||||
return super.onPrepareOptionsMenu(menu)
|
return super.onPrepareOptionsMenu(menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.nav_remove_items -> {
|
R.id.nav_remove_items -> actionHelper.startRemove()
|
||||||
removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback())
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.nav_show_invalidated -> {
|
R.id.nav_show_invalidated -> {
|
||||||
showInvalidated = true
|
showInvalidated = true
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_invalidated_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.nav_hide_invalidated -> {
|
R.id.nav_hide_invalidated -> {
|
||||||
showInvalidated = false
|
showInvalidated = false
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.hide_invalidated_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class RemoveActionModeCallback : ActionMode.Callback {
|
private fun getConfirmationText(selectedItems: SparseArray<TemporaryBasal>): String {
|
||||||
|
|
||||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean {
|
|
||||||
mode.menuInflater.inflate(R.menu.menu_delete_selection, menu)
|
|
||||||
selectedItems.clear()
|
|
||||||
mode.title = rh.gs(R.string.count_selected, selectedItems.size())
|
|
||||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false
|
|
||||||
|
|
||||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
|
||||||
return when (item.itemId) {
|
|
||||||
R.id.remove_selected -> {
|
|
||||||
removeSelected()
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
|
||||||
removeActionMode = null
|
|
||||||
binding.recyclerview.adapter?.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getConfirmationText(): String {
|
|
||||||
if (selectedItems.size() == 1) {
|
if (selectedItems.size() == 1) {
|
||||||
val tempBasal = selectedItems.valueAt(0)
|
val tempBasal = selectedItems.valueAt(0)
|
||||||
val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED
|
val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED
|
||||||
|
@ -294,11 +270,11 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeSelected() {
|
private fun removeSelected(selectedItems: SparseArray<TemporaryBasal>) {
|
||||||
if (selectedItems.size() > 0)
|
if (selectedItems.size() > 0)
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable {
|
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(selectedItems), Runnable {
|
||||||
selectedItems.forEach {_, tempBasal ->
|
selectedItems.forEach { _, tempBasal ->
|
||||||
var extendedBolus: ExtendedBolus? = null
|
var extendedBolus: ExtendedBolus? = null
|
||||||
val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED
|
val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED
|
||||||
if (isFakeExtended) {
|
if (isFakeExtended) {
|
||||||
|
@ -330,10 +306,8 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() {
|
||||||
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) })
|
{ aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
removeActionMode?.finish()
|
actionHelper.finish()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else
|
|
||||||
removeActionMode?.finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,23 +13,22 @@ import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
||||||
import info.nightscout.androidaps.databinding.TreatmentsUserEntryFragmentBinding
|
import info.nightscout.androidaps.databinding.TreatmentsUserEntryFragmentBinding
|
||||||
import info.nightscout.androidaps.databinding.TreatmentsUserEntryItemBinding
|
import info.nightscout.androidaps.databinding.TreatmentsUserEntryItemBinding
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||||
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.interfaces.ImportExportPrefs
|
import info.nightscout.androidaps.interfaces.ImportExportPrefs
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.events.EventTreatmentUpdateGui
|
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
|
import info.nightscout.androidaps.utils.ToastUtils
|
||||||
import info.nightscout.androidaps.utils.Translator
|
import info.nightscout.androidaps.utils.Translator
|
||||||
import info.nightscout.androidaps.utils.userEntry.UserEntryPresentationHelper
|
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.androidaps.utils.userEntry.UserEntryPresentationHelper
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class TreatmentsUserEntryFragment : DaggerFragment() {
|
class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
|
@ -47,9 +46,9 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
@Inject lateinit var userEntryPresentationHelper: UserEntryPresentationHelper
|
@Inject lateinit var userEntryPresentationHelper: UserEntryPresentationHelper
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
private val millsToThePastFiltered = T.days(30).msecs()
|
private val millsToThePastFiltered = T.days(30).msecs()
|
||||||
private val millsToThePastUnFiltered = T.days(3).msecs()
|
private val millsToThePastUnFiltered = T.days(3).msecs()
|
||||||
|
private var menu: Menu? = null
|
||||||
private var showLoop = false
|
private var showLoop = false
|
||||||
private var _binding: TreatmentsUserEntryFragmentBinding? = null
|
private var _binding: TreatmentsUserEntryFragmentBinding? = null
|
||||||
|
|
||||||
|
@ -64,9 +63,11 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
|
binding.recyclerview.emptyView = binding.noRecordsText
|
||||||
|
binding.recyclerview.loadingView = binding.progressBar
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exportUserEnteries() {
|
private fun exportUserEntries() {
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.ue_export_to_csv) + "?") {
|
OKDialog.showConfirmation(activity, rh.gs(R.string.ue_export_to_csv) + "?") {
|
||||||
uel.log(Action.EXPORT_CSV, Sources.Treatments)
|
uel.log(Action.EXPORT_CSV, Sources.Treatments)
|
||||||
|
@ -77,6 +78,7 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
|
|
||||||
fun swapAdapter() {
|
fun swapAdapter() {
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
|
binding.recyclerview.isLoading = true
|
||||||
disposable +=
|
disposable +=
|
||||||
if (showLoop)
|
if (showLoop)
|
||||||
repository
|
repository
|
||||||
|
@ -94,16 +96,10 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
swapAdapter()
|
swapAdapter()
|
||||||
|
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventPreferenceChange::class.java)
|
.toObservable(EventPreferenceChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventTreatmentUpdateGui::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
@ -128,19 +124,18 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: UserEntryViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: UserEntryViewHolder, position: Int) {
|
||||||
val current = entries[position]
|
val current = entries[position]
|
||||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(current.timestamp, entries[position - 1].timestamp)
|
val newDay = position == 0 || !dateUtil.isSameDayGroup(current.timestamp, entries[position - 1].timestamp)
|
||||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
holder.binding.date.visibility = newDay.toVisibility()
|
||||||
holder.binding.date.text = dateUtil.dateString(current.timestamp)
|
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(current.timestamp, rh) else ""
|
||||||
holder.binding.time.text = dateUtil.timeStringWithSeconds(current.timestamp)
|
holder.binding.time.text = dateUtil.timeStringWithSeconds(current.timestamp)
|
||||||
holder.binding.action.text = userEntryPresentationHelper.actionToColoredString(current.action)
|
holder.binding.action.text = userEntryPresentationHelper.actionToColoredString(current.action)
|
||||||
holder.binding.notes.text = current.note
|
holder.binding.notes.text = current.note
|
||||||
holder.binding.notes.visibility = if (current.note != "") View.VISIBLE else View.GONE
|
holder.binding.notes.visibility = (current.note != "").toVisibility()
|
||||||
holder.binding.iconSource.setImageResource(userEntryPresentationHelper.iconId(current.source))
|
holder.binding.iconSource.setImageResource(userEntryPresentationHelper.iconId(current.source))
|
||||||
holder.binding.iconSource.visibility = View.VISIBLE
|
|
||||||
holder.binding.values.text = userEntryPresentationHelper.listToPresentationString(current.values)
|
holder.binding.values.text = userEntryPresentationHelper.listToPresentationString(current.values)
|
||||||
holder.binding.values.visibility = if (holder.binding.values.text != "") View.VISIBLE else View.GONE
|
holder.binding.values.visibility = (holder.binding.values.text != "").toVisibility()
|
||||||
val nextTimestamp = if (entries.size != position + 1) entries[position + 1].timestamp else 0L
|
val nextTimestamp = if (entries.size != position + 1) entries[position + 1].timestamp else 0L
|
||||||
holder.binding.delimiter.visibility = dateUtil.isSameDay(current.timestamp, nextTimestamp).toVisibility()
|
holder.binding.delimiter.visibility = dateUtil.isSameDayGroup(current.timestamp, nextTimestamp).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class UserEntryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
inner class UserEntryViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
@ -152,14 +147,18 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
this.menu = menu
|
||||||
inflater.inflate(R.menu.menu_treatments_user_entry, menu)
|
inflater.inflate(R.menu.menu_treatments_user_entry, menu)
|
||||||
super.onCreateOptionsMenu(menu, inflater)
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
private fun updateMenuVisibility() {
|
||||||
menu.findItem(R.id.nav_hide_loop)?.isVisible = showLoop
|
menu?.findItem(R.id.nav_hide_loop)?.isVisible = showLoop
|
||||||
menu.findItem(R.id.nav_show_loop)?.isVisible = !showLoop
|
menu?.findItem(R.id.nav_show_loop)?.isVisible = !showLoop
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
|
updateMenuVisibility()
|
||||||
return super.onPrepareOptionsMenu(menu)
|
return super.onPrepareOptionsMenu(menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,21 +166,26 @@ class TreatmentsUserEntryFragment : DaggerFragment() {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.nav_show_loop -> {
|
R.id.nav_show_loop -> {
|
||||||
showLoop = true
|
showLoop = true
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_loop_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.nav_hide_loop -> {
|
R.id.nav_hide_loop -> {
|
||||||
showLoop = false
|
showLoop = false
|
||||||
rxBus.send(EventTreatmentUpdateGui())
|
updateMenuVisibility()
|
||||||
|
ToastUtils.showToastInUiThread(context, rh.gs(R.string.show_hide_records))
|
||||||
|
swapAdapter()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.nav_export -> {
|
R.id.nav_export -> {
|
||||||
exportUserEnteries()
|
exportUserEntries()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,11 @@ class CompatDBHelper @Inject constructor(
|
||||||
rxBus.send(EventExtendedBolusChange())
|
rxBus.send(EventExtendedBolusChange())
|
||||||
rxBus.send(EventNewHistoryData(timestamp, false))
|
rxBus.send(EventNewHistoryData(timestamp, false))
|
||||||
}
|
}
|
||||||
|
it.filterIsInstance<EffectiveProfileSwitch>().firstOrNull()?.let { eps ->
|
||||||
|
aapsLogger.debug(LTag.DATABASE, "Firing EventEffectiveProfileSwitchChanged $eps")
|
||||||
|
rxBus.send(EventEffectiveProfileSwitchChanged(eps))
|
||||||
|
rxBus.send(EventNewHistoryData(eps.timestamp, false))
|
||||||
|
}
|
||||||
it.filterIsInstance<TemporaryTarget>().firstOrNull()?.let { tt ->
|
it.filterIsInstance<TemporaryTarget>().firstOrNull()?.let { tt ->
|
||||||
aapsLogger.debug(LTag.DATABASE, "Firing EventTempTargetChange $tt")
|
aapsLogger.debug(LTag.DATABASE, "Firing EventTempTargetChange $tt")
|
||||||
rxBus.send(EventTempTargetChange())
|
rxBus.send(EventTempTargetChange())
|
||||||
|
@ -76,10 +81,6 @@ class CompatDBHelper @Inject constructor(
|
||||||
aapsLogger.debug(LTag.DATABASE, "Firing EventProfileSwitchChanged $ps")
|
aapsLogger.debug(LTag.DATABASE, "Firing EventProfileSwitchChanged $ps")
|
||||||
rxBus.send(EventProfileSwitchChanged())
|
rxBus.send(EventProfileSwitchChanged())
|
||||||
}
|
}
|
||||||
it.filterIsInstance<EffectiveProfileSwitch>().firstOrNull()?.let { eps ->
|
|
||||||
aapsLogger.debug(LTag.DATABASE, "Firing EventEffectiveProfileSwitchChanged $eps")
|
|
||||||
rxBus.send(EventEffectiveProfileSwitchChanged(eps))
|
|
||||||
}
|
|
||||||
it.filterIsInstance<OfflineEvent>().firstOrNull()?.let { oe ->
|
it.filterIsInstance<OfflineEvent>().firstOrNull()?.let { oe ->
|
||||||
aapsLogger.debug(LTag.DATABASE, "Firing EventOfflineChange $oe")
|
aapsLogger.debug(LTag.DATABASE, "Firing EventOfflineChange $oe")
|
||||||
rxBus.send(EventOfflineChange())
|
rxBus.send(EventOfflineChange())
|
||||||
|
|
|
@ -8,8 +8,6 @@ import info.nightscout.androidaps.plugins.aps.openAPSAMA.DetermineBasalResultAMA
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS
|
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalAdapterSMBJS
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
|
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.DetermineBasalAdapterSMBDynamicISFJS
|
import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.DetermineBasalAdapterSMBDynamicISFJS
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobOref1Thread
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobThread
|
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
|
@ -21,6 +19,4 @@ abstract class APSModule {
|
||||||
@ContributesAndroidInjector abstract fun determineBasalAdapterAMAJSInjector(): DetermineBasalAdapterAMAJS
|
@ContributesAndroidInjector abstract fun determineBasalAdapterAMAJSInjector(): DetermineBasalAdapterAMAJS
|
||||||
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS
|
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBJSInjector(): DetermineBasalAdapterSMBJS
|
||||||
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBAutoISFJSInjector(): DetermineBasalAdapterSMBDynamicISFJS
|
@ContributesAndroidInjector abstract fun determineBasalAdapterSMBAutoISFJSInjector(): DetermineBasalAdapterSMBDynamicISFJS
|
||||||
@ContributesAndroidInjector abstract fun iobCobThreadInjector(): IobCobThread
|
|
||||||
@ContributesAndroidInjector abstract fun iobCobOref1ThreadInjector(): IobCobOref1Thread
|
|
||||||
}
|
}
|
|
@ -46,6 +46,7 @@ import javax.inject.Singleton
|
||||||
OmnipodDashModule::class,
|
OmnipodDashModule::class,
|
||||||
OmnipodErosModule::class,
|
OmnipodErosModule::class,
|
||||||
APSModule::class,
|
APSModule::class,
|
||||||
|
WorkflowModule::class,
|
||||||
PreferencesModule::class,
|
PreferencesModule::class,
|
||||||
OverviewModule::class,
|
OverviewModule::class,
|
||||||
DataClassesModule::class,
|
DataClassesModule::class,
|
||||||
|
|
|
@ -32,6 +32,7 @@ import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin
|
||||||
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin
|
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin
|
||||||
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin
|
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin
|
||||||
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin
|
||||||
|
import info.nightscout.androidaps.plugins.general.themes.ThemeSwitcherPlugin
|
||||||
import info.nightscout.androidaps.plugins.general.wear.WearPlugin
|
import info.nightscout.androidaps.plugins.general.wear.WearPlugin
|
||||||
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatusLinePlugin
|
import info.nightscout.androidaps.plugins.general.xdripStatusline.StatusLinePlugin
|
||||||
import info.nightscout.androidaps.plugins.insulin.InsulinLyumjevPlugin
|
import info.nightscout.androidaps.plugins.insulin.InsulinLyumjevPlugin
|
||||||
|
@ -393,6 +394,12 @@ abstract class PluginsModule {
|
||||||
@IntKey(490)
|
@IntKey(490)
|
||||||
abstract fun bindConfigBuilderPlugin(plugin: ConfigBuilderPlugin): PluginBase
|
abstract fun bindConfigBuilderPlugin(plugin: ConfigBuilderPlugin): PluginBase
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@AllConfigs
|
||||||
|
@IntoMap
|
||||||
|
@IntKey(500)
|
||||||
|
abstract fun bindThemeSwitcherPlugin(plugin: ThemeSwitcherPlugin): PluginBase
|
||||||
|
|
||||||
@Qualifier
|
@Qualifier
|
||||||
annotation class AllConfigs
|
annotation class AllConfigs
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,11 @@ package info.nightscout.androidaps.di
|
||||||
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.android.ContributesAndroidInjector
|
import dagger.android.ContributesAndroidInjector
|
||||||
|
import info.nightscout.androidaps.plugins.aps.loop.CarbSuggestionReceiver
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkBluetoothStateReceiver
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkBluetoothStateReceiver
|
||||||
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkBroadcastReceiver
|
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkBroadcastReceiver
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.CarbSuggestionReceiver
|
|
||||||
import info.nightscout.androidaps.receivers.*
|
import info.nightscout.androidaps.receivers.*
|
||||||
|
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
abstract class ReceiversModule {
|
abstract class ReceiversModule {
|
||||||
|
@ -16,8 +15,7 @@ abstract class ReceiversModule {
|
||||||
@ContributesAndroidInjector abstract fun contributesBTReceiver(): BTReceiver
|
@ContributesAndroidInjector abstract fun contributesBTReceiver(): BTReceiver
|
||||||
@ContributesAndroidInjector abstract fun contributesChargingStateReceiver(): ChargingStateReceiver
|
@ContributesAndroidInjector abstract fun contributesChargingStateReceiver(): ChargingStateReceiver
|
||||||
@ContributesAndroidInjector abstract fun contributesDataReceiver(): DataReceiver
|
@ContributesAndroidInjector abstract fun contributesDataReceiver(): DataReceiver
|
||||||
@ContributesAndroidInjector abstract fun contributesKeepAliveReceiver(): KeepAliveReceiver
|
@ContributesAndroidInjector abstract fun contributesKeepAliveWorker(): KeepAliveWorker
|
||||||
@ContributesAndroidInjector abstract fun contributesKeepAliveWorker(): KeepAliveReceiver.KeepAliveWorker
|
|
||||||
@ContributesAndroidInjector abstract fun contributesRileyLinkBluetoothStateReceiver(): RileyLinkBluetoothStateReceiver
|
@ContributesAndroidInjector abstract fun contributesRileyLinkBluetoothStateReceiver(): RileyLinkBluetoothStateReceiver
|
||||||
@ContributesAndroidInjector abstract fun contributesSmsReceiver(): SmsReceiver
|
@ContributesAndroidInjector abstract fun contributesSmsReceiver(): SmsReceiver
|
||||||
@ContributesAndroidInjector abstract fun contributesTimeDateOrTZChangeReceiver(): TimeDateOrTZChangeReceiver
|
@ContributesAndroidInjector abstract fun contributesTimeDateOrTZChangeReceiver(): TimeDateOrTZChangeReceiver
|
||||||
|
|
|
@ -2,10 +2,16 @@ package info.nightscout.androidaps.di
|
||||||
|
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.android.ContributesAndroidInjector
|
import dagger.android.ContributesAndroidInjector
|
||||||
|
import info.nightscout.androidaps.widget.WidgetConfigureActivity
|
||||||
import info.nightscout.androidaps.skins.SkinListPreference
|
import info.nightscout.androidaps.skins.SkinListPreference
|
||||||
|
import info.nightscout.androidaps.widget.Widget
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
abstract class UIModule {
|
abstract class UIModule {
|
||||||
|
|
||||||
@ContributesAndroidInjector abstract fun skinListPreferenceInjector(): SkinListPreference
|
@ContributesAndroidInjector abstract fun skinListPreferenceInjector(): SkinListPreference
|
||||||
|
@ContributesAndroidInjector abstract fun aapsWidgetInjector(): Widget
|
||||||
|
@ContributesAndroidInjector abstract fun contributesWidgetConfigureActivity(): WidgetConfigureActivity
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package info.nightscout.androidaps.di
|
||||||
|
|
||||||
|
import dagger.Module
|
||||||
|
import dagger.android.ContributesAndroidInjector
|
||||||
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.*
|
||||||
|
import info.nightscout.androidaps.workflow.*
|
||||||
|
|
||||||
|
@Module
|
||||||
|
@Suppress("unused")
|
||||||
|
abstract class WorkflowModule {
|
||||||
|
|
||||||
|
@ContributesAndroidInjector abstract fun iobCobWorkerInjector(): IobCobOrefWorker
|
||||||
|
@ContributesAndroidInjector abstract fun iobCobOref1WorkerInjector(): IobCobOref1Worker
|
||||||
|
@ContributesAndroidInjector abstract fun prepareIobAutosensDataWorkerInjector(): PrepareIobAutosensGraphDataWorker
|
||||||
|
@ContributesAndroidInjector abstract fun prepareBasalDataWorkerInjector(): PrepareBasalDataWorker
|
||||||
|
@ContributesAndroidInjector abstract fun prepareTemporaryTargetDataWorkerInjector(): PrepareTemporaryTargetDataWorker
|
||||||
|
@ContributesAndroidInjector abstract fun prepareTreatmentsDataWorkerInjector(): PrepareTreatmentsDataWorker
|
||||||
|
@ContributesAndroidInjector abstract fun loadIobCobResultsWorkerInjector(): UpdateIobCobSensWorker
|
||||||
|
@ContributesAndroidInjector abstract fun preparePredictionsWorkerInjector(): PreparePredictionsWorker
|
||||||
|
@ContributesAndroidInjector abstract fun updateGraphAndIobWorkerInjector(): UpdateGraphWorker
|
||||||
|
@ContributesAndroidInjector abstract fun prepareBgDataWorkerInjector(): PrepareBgDataWorker
|
||||||
|
@ContributesAndroidInjector abstract fun prepareBucketedDataWorkerInjector(): PrepareBucketedDataWorker
|
||||||
|
@ContributesAndroidInjector abstract fun loadBgDataWorkerInjector(): LoadBgDataWorker
|
||||||
|
@ContributesAndroidInjector abstract fun invokeLoopWorkerInjector(): InvokeLoopWorker
|
||||||
|
}
|
|
@ -64,7 +64,7 @@ class CalibrationDialog : DialogFragmentWithDate() {
|
||||||
binding.bg.setParams(savedInstanceState?.getDouble("bg")
|
binding.bg.setParams(savedInstanceState?.getDouble("bg")
|
||||||
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok)
|
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok)
|
||||||
binding.units.text = if (units == GlucoseUnit.MMOL) rh.gs(R.string.mmol) else rh.gs(R.string.mgdl)
|
binding.units.text = if (units == GlucoseUnit.MMOL) rh.gs(R.string.mmol) else rh.gs(R.string.mgdl)
|
||||||
binding.bg.editText?.id?.let { binding.bgLabel.labelFor = it }
|
binding.bgLabel.labelFor = binding.bg.editTextId
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -27,6 +27,8 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProv
|
||||||
import info.nightscout.androidaps.queue.Callback
|
import info.nightscout.androidaps.queue.Callback
|
||||||
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.protection.ProtectionCheck
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.BOLUS
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
@ -50,6 +52,7 @@ class CarbsDialog : DialogFragmentWithDate() {
|
||||||
@Inject lateinit var bolusTimer: BolusTimer
|
@Inject lateinit var bolusTimer: BolusTimer
|
||||||
@Inject lateinit var commandQueue: CommandQueue
|
@Inject lateinit var commandQueue: CommandQueue
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
@ -58,6 +61,7 @@ class CarbsDialog : DialogFragmentWithDate() {
|
||||||
private const val FAV3_DEFAULT = 20
|
private const val FAV3_DEFAULT = 20
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var queryingProtection = false
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
private val textWatcher: TextWatcher = object : TextWatcher {
|
private val textWatcher: TextWatcher = object : TextWatcher {
|
||||||
|
@ -195,9 +199,9 @@ class CarbsDialog : DialogFragmentWithDate() {
|
||||||
binding.hypoTt.isChecked = false
|
binding.hypoTt.isChecked = false
|
||||||
binding.activityTt.isChecked = false
|
binding.activityTt.isChecked = false
|
||||||
}
|
}
|
||||||
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
|
binding.durationLabel.labelFor = binding.duration.editTextId
|
||||||
binding.time.editText?.id?.let { binding.timeLabel.labelFor = it }
|
binding.timeLabel.labelFor = binding.time.editTextId
|
||||||
binding.carbs.editText?.id?.let { binding.carbsLabel.labelFor = it }
|
binding.carbsLabel.labelFor = binding.carbs.editTextId
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -230,8 +234,9 @@ class CarbsDialog : DialogFragmentWithDate() {
|
||||||
if (activitySelected)
|
if (activitySelected)
|
||||||
actions.add(
|
actions.add(
|
||||||
rh.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(activityTT) + " " + unitLabel + " (" + rh.gs(R.string.format_mins, activityTTDuration) + ")").formatColor(
|
rh.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(activityTT) + " " + unitLabel + " (" + rh.gs(R.string.format_mins, activityTTDuration) + ")").formatColor(
|
||||||
|
context,
|
||||||
rh,
|
rh,
|
||||||
R.color.tempTargetConfirmation
|
R.attr.tempTargetConfirmation
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val eatingSoonSelected = binding.eatingSoonTt.isChecked
|
val eatingSoonSelected = binding.eatingSoonTt.isChecked
|
||||||
|
@ -240,27 +245,27 @@ class CarbsDialog : DialogFragmentWithDate() {
|
||||||
rh.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + rh.gs(
|
rh.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + rh.gs(
|
||||||
R.string.format_mins,
|
R.string.format_mins,
|
||||||
eatingSoonTTDuration
|
eatingSoonTTDuration
|
||||||
) + ")").formatColor(rh, R.color.tempTargetConfirmation)
|
) + ")").formatColor(context, rh, R.attr.tempTargetConfirmation)
|
||||||
)
|
)
|
||||||
val hypoSelected = binding.hypoTt.isChecked
|
val hypoSelected = binding.hypoTt.isChecked
|
||||||
if (hypoSelected)
|
if (hypoSelected)
|
||||||
actions.add(
|
actions.add(
|
||||||
rh.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(hypoTT) + " " + unitLabel + " (" + rh.gs(R.string.format_mins, hypoTTDuration) + ")").formatColor(
|
rh.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(hypoTT) + " " + unitLabel + " (" + rh.gs(R.string.format_mins, hypoTTDuration) + ")").formatColor( context,
|
||||||
rh,
|
rh,
|
||||||
R.color.tempTargetConfirmation
|
R.attr.tempTargetConfirmation
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val timeOffset = binding.time.value.toInt()
|
val timeOffset = binding.time.value.toInt()
|
||||||
if (useAlarm && carbs > 0 && timeOffset > 0)
|
if (useAlarm && carbs > 0 && timeOffset > 0)
|
||||||
actions.add(rh.gs(R.string.alarminxmin, timeOffset).formatColor(rh, R.color.info))
|
actions.add(rh.gs(R.string.alarminxmin, timeOffset).formatColor(context , rh, R.attr.infoColor))
|
||||||
val duration = binding.duration.value.toInt()
|
val duration = binding.duration.value.toInt()
|
||||||
if (duration > 0)
|
if (duration > 0)
|
||||||
actions.add(rh.gs(R.string.duration) + ": " + duration + rh.gs(R.string.shorthour))
|
actions.add(rh.gs(R.string.duration) + ": " + duration + rh.gs(R.string.shorthour))
|
||||||
if (carbsAfterConstraints > 0) {
|
if (carbsAfterConstraints > 0) {
|
||||||
actions.add(rh.gs(R.string.carbs) + ": " + "<font color='" + rh.gc(R.color.carbs) + "'>" + rh.gs(R.string.format_carbs, carbsAfterConstraints) + "</font>")
|
actions.add(rh.gs(R.string.carbs) + ": " + "<font color='" + rh.gac(context, R.attr.carbsColor) + "'>" + rh.gs(R.string.format_carbs, carbsAfterConstraints) + "</font>")
|
||||||
if (carbsAfterConstraints != carbs)
|
if (carbsAfterConstraints != carbs)
|
||||||
actions.add("<font color='" + rh.gc(R.color.warning) + "'>" + rh.gs(R.string.carbsconstraintapplied) + "</font>")
|
actions.add("<font color='" + rh.gac(context, R.attr.warningColor) + "'>" + rh.gs(R.string.carbsconstraintapplied) + "</font>")
|
||||||
}
|
}
|
||||||
val notes = binding.notesLayout.notes.text.toString()
|
val notes = binding.notesLayout.notes.text.toString()
|
||||||
if (notes.isNotEmpty())
|
if (notes.isNotEmpty())
|
||||||
|
@ -377,4 +382,20 @@ class CarbsDialog : DialogFragmentWithDate() {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if(!queryingProtection) {
|
||||||
|
queryingProtection = true
|
||||||
|
activity?.let { activity ->
|
||||||
|
val cancelFail = {
|
||||||
|
queryingProtection = false
|
||||||
|
aapsLogger.debug(LTag.APS, "Dialog canceled on resume protection: ${this.javaClass.name}")
|
||||||
|
ToastUtils.showToastInUiThread(ctx, R.string.dialog_canceled)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
protectionCheck.queryProtection(activity, BOLUS, { queryingProtection = false }, cancelFail, cancelFail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -165,8 +165,8 @@ class CareDialog : DialogFragmentWithDate() {
|
||||||
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, binding.okcancel.ok)
|
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, binding.okcancel.ok)
|
||||||
if (options == EventType.NOTE || options == EventType.QUESTION || options == EventType.ANNOUNCEMENT || options == EventType.EXERCISE)
|
if (options == EventType.NOTE || options == EventType.QUESTION || options == EventType.ANNOUNCEMENT || options == EventType.EXERCISE)
|
||||||
binding.notesLayout.root.visibility = View.VISIBLE // independent to preferences
|
binding.notesLayout.root.visibility = View.VISIBLE // independent to preferences
|
||||||
binding.bg.editText?.id?.let { binding.bgLabel.labelFor = it }
|
binding.bgLabel.labelFor = binding.bg.editTextId
|
||||||
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
|
binding.durationLabel.labelFor = binding.duration.editTextId
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
|
|
@ -22,7 +22,11 @@ import info.nightscout.androidaps.utils.HtmlHelper
|
||||||
import info.nightscout.shared.SafeParse
|
import info.nightscout.shared.SafeParse
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.extensions.formatColor
|
import info.nightscout.androidaps.extensions.formatColor
|
||||||
|
import info.nightscout.androidaps.utils.ToastUtils
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.BOLUS
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -36,11 +40,12 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
|
||||||
@Inject lateinit var commandQueue: CommandQueue
|
@Inject lateinit var commandQueue: CommandQueue
|
||||||
@Inject lateinit var activePlugin: ActivePlugin
|
@Inject lateinit var activePlugin: ActivePlugin
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
|
|
||||||
|
private var queryingProtection = false
|
||||||
private var _binding: DialogExtendedbolusBinding? = null
|
private var _binding: DialogExtendedbolusBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||||
|
@ -70,8 +75,8 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
|
||||||
val extendedMaxDuration = pumpDescription.extendedBolusMaxDuration
|
val extendedMaxDuration = pumpDescription.extendedBolusMaxDuration
|
||||||
binding.duration.setParams(savedInstanceState?.getDouble("duration")
|
binding.duration.setParams(savedInstanceState?.getDouble("duration")
|
||||||
?: extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, DecimalFormat("0"), false, binding.okcancel.ok)
|
?: extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, DecimalFormat("0"), false, binding.okcancel.ok)
|
||||||
binding.insulin.editText?.id?.let { binding.insulinLabel.labelFor = it }
|
binding.insulinLabel.labelFor = binding.insulin.editTextId
|
||||||
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
|
binding.durationLabel.labelFor = binding.duration.editTextId
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -88,7 +93,7 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
|
||||||
actions.add(rh.gs(R.string.formatinsulinunits, insulinAfterConstraint))
|
actions.add(rh.gs(R.string.formatinsulinunits, insulinAfterConstraint))
|
||||||
actions.add(rh.gs(R.string.duration) + ": " + rh.gs(R.string.format_mins, durationInMinutes))
|
actions.add(rh.gs(R.string.duration) + ": " + rh.gs(R.string.format_mins, durationInMinutes))
|
||||||
if (abs(insulinAfterConstraint - insulin) > 0.01)
|
if (abs(insulinAfterConstraint - insulin) > 0.01)
|
||||||
actions.add(rh.gs(R.string.constraintapllied).formatColor(rh, R.color.warning))
|
actions.add(rh.gs(R.string.constraintapllied).formatColor(context, rh, R.attr.warningColor))
|
||||||
|
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.extended_bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
OKDialog.showConfirmation(activity, rh.gs(R.string.extended_bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
||||||
|
@ -106,4 +111,20 @@ class ExtendedBolusDialog : DialogFragmentWithDate() {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if(!queryingProtection) {
|
||||||
|
queryingProtection = true
|
||||||
|
activity?.let { activity ->
|
||||||
|
val cancelFail = {
|
||||||
|
queryingProtection = false
|
||||||
|
aapsLogger.debug(LTag.APS, "Dialog canceled on resume protection: ${this.javaClass.name}")
|
||||||
|
ToastUtils.showToastInUiThread(ctx, R.string.dialog_canceled)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
protectionCheck.queryProtection(activity, BOLUS, { queryingProtection = false }, cancelFail, cancelFail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -28,6 +28,9 @@ import info.nightscout.androidaps.utils.HtmlHelper
|
||||||
import info.nightscout.shared.SafeParse
|
import info.nightscout.shared.SafeParse
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.extensions.formatColor
|
import info.nightscout.androidaps.extensions.formatColor
|
||||||
|
import info.nightscout.androidaps.utils.ToastUtils
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.BOLUS
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
@ -44,13 +47,13 @@ class FillDialog : DialogFragmentWithDate() {
|
||||||
@Inject lateinit var activePlugin: ActivePlugin
|
@Inject lateinit var activePlugin: ActivePlugin
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
|
|
||||||
|
private var queryingProtection = false
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
private var _binding: DialogFillBinding? = null
|
private var _binding: DialogFillBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||||
|
@ -96,7 +99,7 @@ class FillDialog : DialogFragmentWithDate() {
|
||||||
} else {
|
} else {
|
||||||
binding.fillPresetButton3.visibility = View.GONE
|
binding.fillPresetButton3.visibility = View.GONE
|
||||||
}
|
}
|
||||||
binding.fillInsulinamount.editText?.id?.let { binding.fillLabel.labelFor = it }
|
binding.fillLabel.labelFor = binding.fillInsulinamount.editTextId
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -113,16 +116,16 @@ class FillDialog : DialogFragmentWithDate() {
|
||||||
if (insulinAfterConstraints > 0) {
|
if (insulinAfterConstraints > 0) {
|
||||||
actions.add(rh.gs(R.string.fillwarning))
|
actions.add(rh.gs(R.string.fillwarning))
|
||||||
actions.add("")
|
actions.add("")
|
||||||
actions.add(rh.gs(R.string.bolus) + ": " + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints, activePlugin.activePump, rh).formatColor(rh, R.color.colorInsulinButton))
|
actions.add(rh.gs(R.string.bolus) + ": " + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints, activePlugin.activePump, rh).formatColor(context, rh, R.attr.insulinButtonColor))
|
||||||
if (abs(insulinAfterConstraints - insulin) > 0.01)
|
if (abs(insulinAfterConstraints - insulin) > 0.01)
|
||||||
actions.add(rh.gs(R.string.bolusconstraintappliedwarn, insulin, insulinAfterConstraints).formatColor(rh, R.color.warning))
|
actions.add(rh.gs(R.string.bolusconstraintappliedwarn, insulin, insulinAfterConstraints).formatColor(context, rh, R.attr.warningColor))
|
||||||
}
|
}
|
||||||
val siteChange = binding.fillCatheterChange.isChecked
|
val siteChange = binding.fillCatheterChange.isChecked
|
||||||
if (siteChange)
|
if (siteChange)
|
||||||
actions.add(rh.gs(R.string.record_pump_site_change).formatColor(rh, R.color.actionsConfirm))
|
actions.add(rh.gs(R.string.record_pump_site_change).formatColor(context, rh, R.attr.actionsConfirmColor))
|
||||||
val insulinChange = binding.fillCartridgeChange.isChecked
|
val insulinChange = binding.fillCartridgeChange.isChecked
|
||||||
if (insulinChange)
|
if (insulinChange)
|
||||||
actions.add(rh.gs(R.string.record_insulin_cartridge_change).formatColor(rh, R.color.actionsConfirm))
|
actions.add(rh.gs(R.string.record_insulin_cartridge_change).formatColor(context, rh, R.attr.actionsConfirmColor))
|
||||||
val notes: String = binding.notesLayout.notes.text.toString()
|
val notes: String = binding.notesLayout.notes.text.toString()
|
||||||
if (notes.isNotEmpty())
|
if (notes.isNotEmpty())
|
||||||
actions.add(rh.gs(R.string.notes_label) + ": " + notes)
|
actions.add(rh.gs(R.string.notes_label) + ": " + notes)
|
||||||
|
@ -196,4 +199,20 @@ class FillDialog : DialogFragmentWithDate() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if(!queryingProtection) {
|
||||||
|
queryingProtection = true
|
||||||
|
activity?.let { activity ->
|
||||||
|
val cancelFail = {
|
||||||
|
queryingProtection = false
|
||||||
|
aapsLogger.debug(LTag.APS, "Dialog canceled on resume protection: ${this.javaClass.name}")
|
||||||
|
ToastUtils.showToastInUiThread(ctx, R.string.dialog_canceled)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
protectionCheck.queryProtection(activity, BOLUS, { queryingProtection = false }, cancelFail, cancelFail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ import info.nightscout.androidaps.queue.Callback
|
||||||
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.extensions.toSignedString
|
import info.nightscout.androidaps.utils.extensions.toSignedString
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.BOLUS
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.shared.SafeParse
|
import info.nightscout.shared.SafeParse
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
@ -52,6 +54,7 @@ class InsulinDialog : DialogFragmentWithDate() {
|
||||||
@Inject lateinit var config: Config
|
@Inject lateinit var config: Config
|
||||||
@Inject lateinit var bolusTimer: BolusTimer
|
@Inject lateinit var bolusTimer: BolusTimer
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
@ -60,7 +63,12 @@ class InsulinDialog : DialogFragmentWithDate() {
|
||||||
private const val PLUS3_DEFAULT = 2.0
|
private const val PLUS3_DEFAULT = 2.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var queryingProtection = false
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
private var _binding: DialogInsulinBinding? = null
|
||||||
|
|
||||||
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private val textWatcher: TextWatcher = object : TextWatcher {
|
private val textWatcher: TextWatcher = object : TextWatcher {
|
||||||
override fun afterTextChanged(s: Editable) {
|
override fun afterTextChanged(s: Editable) {
|
||||||
|
@ -71,12 +79,6 @@ class InsulinDialog : DialogFragmentWithDate() {
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var _binding: DialogInsulinBinding? = null
|
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
|
||||||
|
|
||||||
private fun validateInputs() {
|
private fun validateInputs() {
|
||||||
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
|
val maxInsulin = constraintChecker.getMaxBolusAllowed().value()
|
||||||
if (abs(binding.time.value.toInt()) > 12 * 60) {
|
if (abs(binding.time.value.toInt()) > 12 * 60) {
|
||||||
|
@ -148,8 +150,8 @@ class InsulinDialog : DialogFragmentWithDate() {
|
||||||
binding.recordOnly.setOnCheckedChangeListener { _, isChecked: Boolean ->
|
binding.recordOnly.setOnCheckedChangeListener { _, isChecked: Boolean ->
|
||||||
binding.timeLayout.visibility = isChecked.toVisibility()
|
binding.timeLayout.visibility = isChecked.toVisibility()
|
||||||
}
|
}
|
||||||
binding.amount.editText?.id?.let { binding.insulinLabel.labelFor = it }
|
binding.insulinLabel.labelFor = binding.amount.editTextId
|
||||||
binding.time.editText?.id?.let { binding.timeLabel.labelFor = it }
|
binding.timeLabel.labelFor = binding.time.editTextId
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -170,16 +172,17 @@ class InsulinDialog : DialogFragmentWithDate() {
|
||||||
val eatingSoonChecked = binding.startEatingSoonTt.isChecked
|
val eatingSoonChecked = binding.startEatingSoonTt.isChecked
|
||||||
|
|
||||||
if (insulinAfterConstraints > 0) {
|
if (insulinAfterConstraints > 0) {
|
||||||
actions.add(rh.gs(R.string.bolus) + ": " + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints, activePlugin.activePump, rh).formatColor(rh, R.color.bolus))
|
actions.add(rh.gs(R.string.bolus) + ": " + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints, activePlugin.activePump, rh).formatColor(context, rh, R.attr.bolusColor))
|
||||||
if (recordOnlyChecked)
|
if (recordOnlyChecked)
|
||||||
actions.add(rh.gs(R.string.bolusrecordedonly).formatColor(rh, R.color.warning))
|
actions.add(rh.gs(R.string.bolusrecordedonly).formatColor(context, rh, R.attr.warningColor))
|
||||||
if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
|
if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
|
||||||
actions.add(rh.gs(R.string.bolusconstraintappliedwarn, insulin, insulinAfterConstraints).formatColor(rh, R.color.warning))
|
actions.add(rh.gs(R.string.bolusconstraintappliedwarn, insulin, insulinAfterConstraints).formatColor(context, rh, R.attr.warningColor))
|
||||||
}
|
}
|
||||||
val eatingSoonTTDuration = defaultValueHelper.determineEatingSoonTTDuration()
|
val eatingSoonTTDuration = defaultValueHelper.determineEatingSoonTTDuration()
|
||||||
val eatingSoonTT = defaultValueHelper.determineEatingSoonTT()
|
val eatingSoonTT = defaultValueHelper.determineEatingSoonTT()
|
||||||
if (eatingSoonChecked)
|
if (eatingSoonChecked)
|
||||||
actions.add(rh.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + rh.gs(R.string.format_mins, eatingSoonTTDuration) + ")").formatColor(rh, R.color.tempTargetConfirmation))
|
actions.add(rh.gs(R.string.temptargetshort) + ": " + (DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + rh.gs(R.string.format_mins, eatingSoonTTDuration) + ")")
|
||||||
|
.formatColor(context, rh, R.attr.tempTargetConfirmation))
|
||||||
|
|
||||||
val timeOffset = binding.time.value.toInt()
|
val timeOffset = binding.time.value.toInt()
|
||||||
val time = dateUtil.now() + T.mins(timeOffset.toLong()).msecs()
|
val time = dateUtil.now() + T.mins(timeOffset.toLong()).msecs()
|
||||||
|
@ -255,4 +258,20 @@ class InsulinDialog : DialogFragmentWithDate() {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if(!queryingProtection) {
|
||||||
|
queryingProtection = true
|
||||||
|
activity?.let { activity ->
|
||||||
|
val cancelFail = {
|
||||||
|
queryingProtection = false
|
||||||
|
aapsLogger.debug(LTag.APS, "Dialog canceled on resume protection: ${this.javaClass.name}")
|
||||||
|
ToastUtils.showToastInUiThread(ctx, R.string.dialog_canceled)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
protectionCheck.queryProtection(activity, BOLUS, { queryingProtection = false }, cancelFail, cancelFail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -38,6 +38,8 @@ import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.utils.ToastUtils
|
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.protection.ProtectionCheck
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.BOLUS
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
@ -62,14 +64,15 @@ class LoopDialog : DaggerDialogFragment() {
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
@Inject lateinit var objectivePlugin: ObjectivesPlugin
|
@Inject lateinit var objectivePlugin: ObjectivesPlugin
|
||||||
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
|
|
||||||
|
private var queryingProtection = false
|
||||||
private var showOkCancel: Boolean = true
|
private var showOkCancel: Boolean = true
|
||||||
private var _binding: DialogLoopBinding? = null
|
private var _binding: DialogLoopBinding? = null
|
||||||
private var handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
|
private var handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
|
||||||
private lateinit var refreshDialog: Runnable
|
private lateinit var refreshDialog: Runnable
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
val disposable = CompositeDisposable()
|
val disposable = CompositeDisposable()
|
||||||
|
@ -437,4 +440,20 @@ class LoopDialog : DaggerDialogFragment() {
|
||||||
aapsLogger.debug(e.localizedMessage ?: e.toString())
|
aapsLogger.debug(e.localizedMessage ?: e.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if(!queryingProtection) {
|
||||||
|
queryingProtection = true
|
||||||
|
activity?.let { activity ->
|
||||||
|
val cancelFail = {
|
||||||
|
queryingProtection = false
|
||||||
|
aapsLogger.debug(LTag.APS, "Dialog canceled on resume protection: ${this.javaClass.name}")
|
||||||
|
ToastUtils.showToastInUiThread(ctx, R.string.dialog_canceled)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
protectionCheck.queryProtection(activity, BOLUS, { queryingProtection = false }, cancelFail, cancelFail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.dialogs
|
package info.nightscout.androidaps.dialogs
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
@ -30,7 +31,10 @@ import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||||
import info.nightscout.androidaps.utils.HardLimits
|
import info.nightscout.androidaps.utils.HardLimits
|
||||||
import info.nightscout.androidaps.utils.HtmlHelper
|
import info.nightscout.androidaps.utils.HtmlHelper
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
|
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.protection.ProtectionCheck
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.BOLUS
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
@ -51,15 +55,15 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
|
||||||
@Inject lateinit var hardLimits: HardLimits
|
@Inject lateinit var hardLimits: HardLimits
|
||||||
@Inject lateinit var rxBus: RxBus
|
@Inject lateinit var rxBus: RxBus
|
||||||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||||
|
@Inject lateinit var ctx: Context
|
||||||
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
|
|
||||||
private var profileIndex: Int? = null
|
private var queryingProtection = false
|
||||||
|
private var profileName: String? = null
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
private var _binding: DialogProfileswitchBinding? = null
|
private var _binding: DialogProfileswitchBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private val textWatcher: TextWatcher = object : TextWatcher {
|
private val textWatcher: TextWatcher = object : TextWatcher {
|
||||||
|
@ -86,7 +90,7 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
|
||||||
): View {
|
): View {
|
||||||
onCreateViewGeneral()
|
onCreateViewGeneral()
|
||||||
arguments?.let { bundle ->
|
arguments?.let { bundle ->
|
||||||
profileIndex = bundle.getInt("profileIndex", 0)
|
profileName = bundle.getString("profileName", null)
|
||||||
}
|
}
|
||||||
_binding = DialogProfileswitchBinding.inflate(inflater, container, false)
|
_binding = DialogProfileswitchBinding.inflate(inflater, container, false)
|
||||||
return binding.root
|
return binding.root
|
||||||
|
@ -112,8 +116,7 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
|
||||||
|
|
||||||
// profile
|
// profile
|
||||||
context?.let { context ->
|
context?.let { context ->
|
||||||
val profileStore = activePlugin.activeProfileSource.profile
|
val profileStore = activePlugin.activeProfileSource.profile ?: return
|
||||||
?: return
|
|
||||||
val profileListToCheck = profileStore.getProfileList()
|
val profileListToCheck = profileStore.getProfileList()
|
||||||
val profileList = ArrayList<CharSequence>()
|
val profileList = ArrayList<CharSequence>()
|
||||||
for (profileName in profileListToCheck) {
|
for (profileName in profileListToCheck) {
|
||||||
|
@ -125,15 +128,16 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
|
||||||
dismiss()
|
dismiss()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList)
|
binding.profileList.setAdapter(ArrayAdapter(context, R.layout.spinner_centered, profileList))
|
||||||
binding.profile.adapter = adapter
|
|
||||||
// set selected to actual profile
|
// set selected to actual profile
|
||||||
if (profileIndex != null)
|
if (profileName != null)
|
||||||
binding.profile.setSelection(profileIndex as Int)
|
binding.profileList.setText(profileName, false)
|
||||||
else
|
else {
|
||||||
|
binding.profileList.setText(profileList[0], false)
|
||||||
for (p in profileList.indices)
|
for (p in profileList.indices)
|
||||||
if (profileList[p] == profileFunction.getOriginalProfileName())
|
if (profileList[p] == profileFunction.getOriginalProfileName())
|
||||||
binding.profile.setSelection(p)
|
binding.profileList.setText(profileList[p], false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
profileFunction.getProfile()?.let { profile ->
|
profileFunction.getProfile()?.let { profile ->
|
||||||
|
@ -148,9 +152,9 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.ttLayout.visibility = View.GONE
|
binding.ttLayout.visibility = View.GONE
|
||||||
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
|
binding.durationLabel.labelFor = binding.duration.editTextId
|
||||||
binding.percentage.editText?.id?.let { binding.percentageLabel.labelFor = it }
|
binding.percentageLabel.labelFor = binding.percentage.editTextId
|
||||||
binding.timeshift.editText?.id?.let { binding.timeshiftLabel.labelFor = it }
|
binding.timeshiftLabel.labelFor = binding.timeshift.editTextId
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -168,7 +172,7 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
|
||||||
val duration = binding.duration.value.toInt()
|
val duration = binding.duration.value.toInt()
|
||||||
if (duration > 0L)
|
if (duration > 0L)
|
||||||
actions.add(rh.gs(R.string.duration) + ": " + rh.gs(R.string.format_mins, duration))
|
actions.add(rh.gs(R.string.duration) + ": " + rh.gs(R.string.format_mins, duration))
|
||||||
val profileName = binding.profile.selectedItem.toString()
|
val profileName = binding.profileList.text.toString()
|
||||||
actions.add(rh.gs(R.string.profile) + ": " + profileName)
|
actions.add(rh.gs(R.string.profile) + ": " + profileName)
|
||||||
val percent = binding.percentage.value.toInt()
|
val percent = binding.percentage.value.toInt()
|
||||||
if (percent != 100)
|
if (percent != 100)
|
||||||
|
@ -245,4 +249,20 @@ class ProfileSwitchDialog : DialogFragmentWithDate() {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if(!queryingProtection) {
|
||||||
|
queryingProtection = true
|
||||||
|
activity?.let { activity ->
|
||||||
|
val cancelFail = {
|
||||||
|
queryingProtection = false
|
||||||
|
aapsLogger.debug(LTag.APS, "Dialog canceled on resume protection: ${this.javaClass.name}")
|
||||||
|
ToastUtils.showToastInUiThread(ctx, R.string.dialog_canceled)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
protectionCheck.queryProtection(activity, BOLUS, { queryingProtection = false }, cancelFail, cancelFail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,11 @@ import info.nightscout.androidaps.utils.HtmlHelper
|
||||||
import info.nightscout.shared.SafeParse
|
import info.nightscout.shared.SafeParse
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.extensions.formatColor
|
import info.nightscout.androidaps.extensions.formatColor
|
||||||
|
import info.nightscout.androidaps.utils.ToastUtils
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.BOLUS
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -35,13 +39,13 @@ class TempBasalDialog : DialogFragmentWithDate() {
|
||||||
@Inject lateinit var commandQueue: CommandQueue
|
@Inject lateinit var commandQueue: CommandQueue
|
||||||
@Inject lateinit var ctx: Context
|
@Inject lateinit var ctx: Context
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
|
|
||||||
|
private var queryingProtection = false
|
||||||
private var isPercentPump = true
|
private var isPercentPump = true
|
||||||
|
|
||||||
private var _binding: DialogTempbasalBinding? = null
|
private var _binding: DialogTempbasalBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||||
|
@ -51,8 +55,7 @@ class TempBasalDialog : DialogFragmentWithDate() {
|
||||||
savedInstanceState.putDouble("basalAbsoluteInput", binding.basalAbsoluteInput.value)
|
savedInstanceState.putDouble("basalAbsoluteInput", binding.basalAbsoluteInput.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
savedInstanceState: Bundle?): View {
|
|
||||||
onCreateViewGeneral()
|
onCreateViewGeneral()
|
||||||
_binding = DialogTempbasalBinding.inflate(inflater, container, false)
|
_binding = DialogTempbasalBinding.inflate(inflater, container, false)
|
||||||
return binding.root
|
return binding.root
|
||||||
|
@ -86,9 +89,9 @@ class TempBasalDialog : DialogFragmentWithDate() {
|
||||||
binding.percentLayout.visibility = View.GONE
|
binding.percentLayout.visibility = View.GONE
|
||||||
binding.absoluteLayout.visibility = View.VISIBLE
|
binding.absoluteLayout.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
binding.basalPercentInput.editText?.id?.let { binding.basalPercentLabel.labelFor = it }
|
binding.basalPercentLabel.labelFor = binding.basalPercentInput.editTextId
|
||||||
binding.basalAbsoluteInput.editText?.id?.let { binding.basalAbsoluteLabel.labelFor = it }
|
binding.basalAbsoluteLabel.labelFor = binding.basalAbsoluteInput.editTextId
|
||||||
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
|
binding.durationLabel.labelFor = binding.duration.editTextId
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -115,7 +118,7 @@ class TempBasalDialog : DialogFragmentWithDate() {
|
||||||
actions.add(rh.gs(R.string.tempbasal_label) + ": " + rh.gs(R.string.pump_basebasalrate, absolute))
|
actions.add(rh.gs(R.string.tempbasal_label) + ": " + rh.gs(R.string.pump_basebasalrate, absolute))
|
||||||
actions.add(rh.gs(R.string.duration) + ": " + rh.gs(R.string.format_mins, durationInMinutes))
|
actions.add(rh.gs(R.string.duration) + ": " + rh.gs(R.string.format_mins, durationInMinutes))
|
||||||
if (abs(absolute - basalAbsoluteInput) > 0.01)
|
if (abs(absolute - basalAbsoluteInput) > 0.01)
|
||||||
actions.add(rh.gs(R.string.constraintapllied).formatColor(rh, R.color.warning))
|
actions.add(rh.gs(R.string.constraintapllied).formatColor(context, rh, R.attr.warningColor))
|
||||||
}
|
}
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.tempbasal_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
OKDialog.showConfirmation(activity, rh.gs(R.string.tempbasal_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), {
|
||||||
|
@ -141,4 +144,20 @@ class TempBasalDialog : DialogFragmentWithDate() {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if(!queryingProtection) {
|
||||||
|
queryingProtection = true
|
||||||
|
activity?.let { activity ->
|
||||||
|
val cancelFail = {
|
||||||
|
queryingProtection = false
|
||||||
|
aapsLogger.debug(LTag.APS, "Dialog canceled on resume protection: ${this.javaClass.name}")
|
||||||
|
ToastUtils.showToastInUiThread(ctx, R.string.dialog_canceled)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
protectionCheck.queryProtection(activity, BOLUS, { queryingProtection = false }, cancelFail, cancelFail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.dialogs
|
package info.nightscout.androidaps.dialogs
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
@ -26,7 +27,10 @@ import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
import info.nightscout.androidaps.utils.DefaultValueHelper
|
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||||
import info.nightscout.androidaps.utils.HtmlHelper
|
import info.nightscout.androidaps.utils.HtmlHelper
|
||||||
|
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.protection.ProtectionCheck
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.BOLUS
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
@ -43,15 +47,16 @@ class TempTargetDialog : DialogFragmentWithDate() {
|
||||||
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
@Inject lateinit var defaultValueHelper: DefaultValueHelper
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
|
@Inject lateinit var ctx: Context
|
||||||
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
|
|
||||||
private lateinit var reasonList: List<String>
|
private lateinit var reasonList: List<String>
|
||||||
|
|
||||||
|
private var queryingProtection = false
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
private var _binding: DialogTemptargetBinding? = null
|
private var _binding: DialogTemptargetBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||||
|
@ -60,8 +65,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
|
||||||
savedInstanceState.putDouble("tempTarget", binding.temptarget.value)
|
savedInstanceState.putDouble("tempTarget", binding.temptarget.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
savedInstanceState: Bundle?): View {
|
|
||||||
onCreateViewGeneral()
|
onCreateViewGeneral()
|
||||||
_binding = DialogTemptargetBinding.inflate(inflater, container, false)
|
_binding = DialogTemptargetBinding.inflate(inflater, container, false)
|
||||||
return binding.root
|
return binding.root
|
||||||
|
@ -100,10 +104,9 @@ class TempTargetDialog : DialogFragmentWithDate() {
|
||||||
rh.gs(R.string.activity),
|
rh.gs(R.string.activity),
|
||||||
rh.gs(R.string.hypo)
|
rh.gs(R.string.hypo)
|
||||||
)
|
)
|
||||||
val adapterReason = ArrayAdapter(context, R.layout.spinner_centered, reasonList)
|
binding.reasonList.setAdapter(ArrayAdapter(context, R.layout.spinner_centered, reasonList))
|
||||||
binding.reason.adapter = adapterReason
|
|
||||||
|
|
||||||
binding.targetCancel.setOnClickListener { shortClick(it) }
|
binding.targetCancel.setOnClickListener { binding.duration.value = 0.0; shortClick(it) }
|
||||||
binding.eatingSoon.setOnClickListener { shortClick(it) }
|
binding.eatingSoon.setOnClickListener { shortClick(it) }
|
||||||
binding.activity.setOnClickListener { shortClick(it) }
|
binding.activity.setOnClickListener { shortClick(it) }
|
||||||
binding.hypo.setOnClickListener { shortClick(it) }
|
binding.hypo.setOnClickListener { shortClick(it) }
|
||||||
|
@ -120,8 +123,8 @@ class TempTargetDialog : DialogFragmentWithDate() {
|
||||||
longClick(it)
|
longClick(it)
|
||||||
return@setOnLongClickListener true
|
return@setOnLongClickListener true
|
||||||
}
|
}
|
||||||
binding.duration.editText?.id?.let { binding.durationLabel.labelFor = it }
|
binding.durationLabel.labelFor = binding.duration.editTextId
|
||||||
binding.temptarget.editText?.id?.let { binding.temptargetLabel.labelFor = it }
|
binding.temptargetLabel.labelFor = binding.temptarget.editTextId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,23 +138,19 @@ class TempTargetDialog : DialogFragmentWithDate() {
|
||||||
R.id.eating_soon -> {
|
R.id.eating_soon -> {
|
||||||
binding.temptarget.value = defaultValueHelper.determineEatingSoonTT()
|
binding.temptarget.value = defaultValueHelper.determineEatingSoonTT()
|
||||||
binding.duration.value = defaultValueHelper.determineEatingSoonTTDuration().toDouble()
|
binding.duration.value = defaultValueHelper.determineEatingSoonTTDuration().toDouble()
|
||||||
binding.reason.setSelection(reasonList.indexOf(rh.gs(R.string.eatingsoon)))
|
binding.reasonList.setText(rh.gs(R.string.eatingsoon), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.activity -> {
|
R.id.activity -> {
|
||||||
binding.temptarget.value = defaultValueHelper.determineActivityTT()
|
binding.temptarget.value = defaultValueHelper.determineActivityTT()
|
||||||
binding.duration.value = defaultValueHelper.determineActivityTTDuration().toDouble()
|
binding.duration.value = defaultValueHelper.determineActivityTTDuration().toDouble()
|
||||||
binding.reason.setSelection(reasonList.indexOf(rh.gs(R.string.activity)))
|
binding.reasonList.setText(rh.gs(R.string.activity), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.hypo -> {
|
R.id.hypo -> {
|
||||||
binding.temptarget.value = defaultValueHelper.determineHypoTT()
|
binding.temptarget.value = defaultValueHelper.determineHypoTT()
|
||||||
binding.duration.value = defaultValueHelper.determineHypoTTDuration().toDouble()
|
binding.duration.value = defaultValueHelper.determineHypoTTDuration().toDouble()
|
||||||
binding.reason.setSelection(reasonList.indexOf(rh.gs(R.string.hypo)))
|
binding.reasonList.setText(rh.gs(R.string.hypo), false)
|
||||||
}
|
|
||||||
|
|
||||||
R.id.cancel -> {
|
|
||||||
binding.duration.value = 0.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +164,7 @@ class TempTargetDialog : DialogFragmentWithDate() {
|
||||||
override fun submit(): Boolean {
|
override fun submit(): Boolean {
|
||||||
if (_binding == null) return false
|
if (_binding == null) return false
|
||||||
val actions: LinkedList<String> = LinkedList()
|
val actions: LinkedList<String> = LinkedList()
|
||||||
var reason = binding.reason.selectedItem?.toString() ?: return false
|
var reason = binding.reasonList.text.toString()
|
||||||
val unitResId = if (profileFunction.getUnits() == GlucoseUnit.MGDL) R.string.mgdl else R.string.mmol
|
val unitResId = if (profileFunction.getUnits() == GlucoseUnit.MGDL) R.string.mgdl else R.string.mmol
|
||||||
val target = binding.temptarget.value
|
val target = binding.temptarget.value
|
||||||
val duration = binding.duration.value.toInt()
|
val duration = binding.duration.value.toInt()
|
||||||
|
@ -222,4 +221,20 @@ class TempTargetDialog : DialogFragmentWithDate() {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if(!queryingProtection) {
|
||||||
|
queryingProtection = true
|
||||||
|
activity?.let { activity ->
|
||||||
|
val cancelFail = {
|
||||||
|
queryingProtection = false
|
||||||
|
aapsLogger.debug(LTag.APS, "Dialog canceled on resume protection: ${this.javaClass.name}")
|
||||||
|
ToastUtils.showToastInUiThread(ctx, R.string.dialog_canceled)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
protectionCheck.queryProtection(activity, BOLUS, { queryingProtection = false }, cancelFail, cancelFail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ import info.nightscout.shared.SafeParse
|
||||||
import info.nightscout.androidaps.utils.ToastUtils
|
import info.nightscout.androidaps.utils.ToastUtils
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.extensions.formatColor
|
import info.nightscout.androidaps.extensions.formatColor
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.BOLUS
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
@ -48,8 +50,14 @@ class TreatmentDialog : DialogFragmentWithDate() {
|
||||||
@Inject lateinit var config: Config
|
@Inject lateinit var config: Config
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
|
|
||||||
|
private var queryingProtection = false
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
private var _binding: DialogTreatmentBinding? = null
|
||||||
|
|
||||||
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private val textWatcher: TextWatcher = object : TextWatcher {
|
private val textWatcher: TextWatcher = object : TextWatcher {
|
||||||
override fun afterTextChanged(s: Editable) {}
|
override fun afterTextChanged(s: Editable) {}
|
||||||
|
@ -72,12 +80,6 @@ class TreatmentDialog : DialogFragmentWithDate() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var _binding: DialogTreatmentBinding? = null
|
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
|
||||||
|
|
||||||
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||||
super.onSaveInstanceState(savedInstanceState)
|
super.onSaveInstanceState(savedInstanceState)
|
||||||
savedInstanceState.putDouble("carbs", binding.carbs.value)
|
savedInstanceState.putDouble("carbs", binding.carbs.value)
|
||||||
|
@ -106,8 +108,8 @@ class TreatmentDialog : DialogFragmentWithDate() {
|
||||||
binding.insulin.setParams(savedInstanceState?.getDouble("insulin")
|
binding.insulin.setParams(savedInstanceState?.getDouble("insulin")
|
||||||
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
|
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
|
||||||
binding.recordOnlyLayout.visibility = View.GONE
|
binding.recordOnlyLayout.visibility = View.GONE
|
||||||
binding.insulin.editText?.id?.let { binding.insulinLabel.labelFor = it }
|
binding.insulinLabel.labelFor = binding.insulin.editTextId
|
||||||
binding.carbs.editText?.id?.let { binding.carbsLabel.labelFor = it }
|
binding.carbsLabel.labelFor = binding.carbs.editTextId
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -126,16 +128,16 @@ class TreatmentDialog : DialogFragmentWithDate() {
|
||||||
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
|
val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value()
|
||||||
|
|
||||||
if (insulinAfterConstraints > 0) {
|
if (insulinAfterConstraints > 0) {
|
||||||
actions.add(rh.gs(R.string.bolus) + ": " + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints, activePlugin.activePump, rh).formatColor(rh, R.color.bolus))
|
actions.add(rh.gs(R.string.bolus) + ": " + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints, activePlugin.activePump, rh).formatColor(context, rh, R.attr.bolusColor))
|
||||||
if (recordOnlyChecked)
|
if (recordOnlyChecked)
|
||||||
actions.add(rh.gs(R.string.bolusrecordedonly).formatColor(rh, R.color.warning))
|
actions.add(rh.gs(R.string.bolusrecordedonly).formatColor(context, rh, R.attr.warningColor))
|
||||||
if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
|
if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
|
||||||
actions.add(rh.gs(R.string.bolusconstraintappliedwarn, insulin, insulinAfterConstraints).formatColor(rh, R.color.warning))
|
actions.add(rh.gs(R.string.bolusconstraintappliedwarn, insulin, insulinAfterConstraints).formatColor(context, rh, R.attr.warningColor))
|
||||||
}
|
}
|
||||||
if (carbsAfterConstraints > 0) {
|
if (carbsAfterConstraints > 0) {
|
||||||
actions.add(rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carbsAfterConstraints).formatColor(rh, R.color.carbs))
|
actions.add(rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carbsAfterConstraints).formatColor(context, rh, R.attr.carbsColor))
|
||||||
if (carbsAfterConstraints != carbs)
|
if (carbsAfterConstraints != carbs)
|
||||||
actions.add(rh.gs(R.string.carbsconstraintapplied).formatColor(rh, R.color.warning))
|
actions.add(rh.gs(R.string.carbsconstraintapplied).formatColor(context, rh, R.attr.warningColor))
|
||||||
}
|
}
|
||||||
if (insulinAfterConstraints > 0 || carbsAfterConstraints > 0) {
|
if (insulinAfterConstraints > 0 || carbsAfterConstraints > 0) {
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
|
@ -201,4 +203,20 @@ class TreatmentDialog : DialogFragmentWithDate() {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if(!queryingProtection) {
|
||||||
|
queryingProtection = true
|
||||||
|
activity?.let { activity ->
|
||||||
|
val cancelFail = {
|
||||||
|
queryingProtection = false
|
||||||
|
aapsLogger.debug(LTag.APS, "Dialog canceled on resume protection: ${this.javaClass.name}")
|
||||||
|
ToastUtils.showToastInUiThread(ctx, R.string.dialog_canceled)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
protectionCheck.queryProtection(activity, BOLUS, { queryingProtection = false }, cancelFail, cancelFail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,16 @@
|
||||||
package info.nightscout.androidaps.dialogs
|
package info.nightscout.androidaps.dialogs
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.Window
|
||||||
|
import android.view.WindowManager
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.AdapterView.OnItemSelectedListener
|
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import android.widget.CompoundButton
|
import android.widget.CompoundButton
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
|
@ -20,22 +24,24 @@ import info.nightscout.androidaps.database.ValueWrapper
|
||||||
import info.nightscout.androidaps.databinding.DialogWizardBinding
|
import info.nightscout.androidaps.databinding.DialogWizardBinding
|
||||||
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
||||||
import info.nightscout.androidaps.extensions.formatColor
|
import info.nightscout.androidaps.extensions.formatColor
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
|
||||||
import info.nightscout.shared.SafeParse
|
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.extensions.valueToUnits
|
import info.nightscout.androidaps.extensions.valueToUnits
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker
|
||||||
import info.nightscout.androidaps.utils.*
|
import info.nightscout.androidaps.utils.*
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.BOLUS
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
|
||||||
import info.nightscout.androidaps.utils.wizard.BolusWizard
|
import info.nightscout.androidaps.utils.wizard.BolusWizard
|
||||||
|
import info.nightscout.shared.SafeParse
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import java.text.DecimalFormat
|
import java.text.DecimalFormat
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
@ -55,16 +61,22 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
@Inject lateinit var iobCobCalculator: IobCobCalculator
|
@Inject lateinit var iobCobCalculator: IobCobCalculator
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
|
|
||||||
|
private var queryingProtection = false
|
||||||
private var wizard: BolusWizard? = null
|
private var wizard: BolusWizard? = null
|
||||||
private var calculatedPercentage = 100.0
|
private var calculatedPercentage = 100.0
|
||||||
private var calculatedCorrection = 0.0
|
private var calculatedCorrection = 0.0
|
||||||
private var correctionPercent = false
|
private var correctionPercent = false
|
||||||
private var carbsPassedIntoWizard = 0.0
|
private var carbsPassedIntoWizard = 0.0
|
||||||
private var notesPassedIntoWizard = ""
|
private var notesPassedIntoWizard = ""
|
||||||
|
private var okClicked: Boolean = false // one shot guards
|
||||||
|
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||||
|
private var bolusStep = 0.0
|
||||||
|
private var _binding: DialogWizardBinding? = null
|
||||||
|
|
||||||
//one shot guards
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
private var okClicked: Boolean = false
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
private val textWatcher = object : TextWatcher {
|
private val textWatcher = object : TextWatcher {
|
||||||
override fun afterTextChanged(s: Editable) {}
|
override fun afterTextChanged(s: Editable) {}
|
||||||
|
@ -83,15 +95,6 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
|
||||||
private var bolusStep = 0.0
|
|
||||||
|
|
||||||
private var _binding: DialogWizardBinding? = null
|
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
@ -106,10 +109,9 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
savedInstanceState.putDouble("carb_time_input", binding.carbTimeInput.value)
|
savedInstanceState.putDouble("carb_time_input", binding.carbTimeInput.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
savedInstanceState: Bundle?): View {
|
|
||||||
this.arguments?.let { bundle ->
|
this.arguments?.let { bundle ->
|
||||||
carbsPassedIntoWizard = bundle.getInt("carbs_input").toDouble()
|
carbsPassedIntoWizard = bundle.getDouble("carbs_input")
|
||||||
notesPassedIntoWizard = bundle.getString("notes_input").toString()
|
notesPassedIntoWizard = bundle.getString("notes_input").toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +130,7 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
val useSuperBolus = sp.getBoolean(R.string.key_usesuperbolus, false)
|
val useSuperBolus = sp.getBoolean(R.string.key_usesuperbolus, false)
|
||||||
binding.sbCheckbox.visibility = useSuperBolus.toVisibility()
|
binding.sbCheckbox.visibility = useSuperBolus.toVisibility()
|
||||||
binding.superBolusRow.visibility = useSuperBolus.toVisibility()
|
binding.superBolusRow.visibility = useSuperBolus.toVisibility()
|
||||||
binding.notesLayout.visibility = sp.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
|
binding.notesLayout.root.visibility = sp.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
|
||||||
|
|
||||||
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value()
|
val maxCarbs = constraintChecker.getMaxCarbsAllowed().value()
|
||||||
val maxCorrection = constraintChecker.getMaxBolusAllowed().value()
|
val maxCorrection = constraintChecker.getMaxBolusAllowed().value()
|
||||||
|
@ -137,14 +139,18 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
if (profileFunction.getUnits() == GlucoseUnit.MGDL) {
|
if (profileFunction.getUnits() == GlucoseUnit.MGDL) {
|
||||||
binding.bgInput.setParams(
|
binding.bgInput.setParams(
|
||||||
savedInstanceState?.getDouble("bg_input")
|
savedInstanceState?.getDouble("bg_input")
|
||||||
?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, timeTextWatcher)
|
?: 0.0, 0.0, 500.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, timeTextWatcher
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
binding.bgInput.setParams(
|
binding.bgInput.setParams(
|
||||||
savedInstanceState?.getDouble("bg_input")
|
savedInstanceState?.getDouble("bg_input")
|
||||||
?: 0.0, 0.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.okcancel.ok, textWatcher)
|
?: 0.0, 0.0, 30.0, 0.1, DecimalFormat("0.0"), false, binding.okcancel.ok, textWatcher
|
||||||
|
)
|
||||||
}
|
}
|
||||||
binding.carbsInput.setParams(savedInstanceState?.getDouble("carbs_input")
|
binding.carbsInput.setParams(
|
||||||
?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher)
|
savedInstanceState?.getDouble("carbs_input")
|
||||||
|
?: 0.0, 0.0, maxCarbs.toDouble(), 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher
|
||||||
|
)
|
||||||
|
|
||||||
if (correctionPercent) {
|
if (correctionPercent) {
|
||||||
calculatedPercentage = sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble()
|
calculatedPercentage = sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble()
|
||||||
|
@ -154,11 +160,14 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
} else {
|
} else {
|
||||||
binding.correctionInput.setParams(
|
binding.correctionInput.setParams(
|
||||||
savedInstanceState?.getDouble("correction_input")
|
savedInstanceState?.getDouble("correction_input")
|
||||||
?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher)
|
?: 0.0, -maxCorrection, maxCorrection, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(activePlugin.activePump), false, binding.okcancel.ok, textWatcher
|
||||||
|
)
|
||||||
binding.correctionUnit.text = rh.gs(R.string.insulin_unit_shortname)
|
binding.correctionUnit.text = rh.gs(R.string.insulin_unit_shortname)
|
||||||
}
|
}
|
||||||
binding.carbTimeInput.setParams(savedInstanceState?.getDouble("carb_time_input")
|
binding.carbTimeInput.setParams(
|
||||||
?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, binding.okcancel.ok, timeTextWatcher)
|
savedInstanceState?.getDouble("carb_time_input")
|
||||||
|
?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, binding.okcancel.ok, timeTextWatcher
|
||||||
|
)
|
||||||
initDialog()
|
initDialog()
|
||||||
calculatedPercentage = sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble()
|
calculatedPercentage = sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble()
|
||||||
binding.percentUsed.text = rh.gs(R.string.format_percent, sp.getInt(R.string.key_boluswizard_percentage, 100))
|
binding.percentUsed.text = rh.gs(R.string.format_percent, sp.getInt(R.string.key_boluswizard_percentage, 100))
|
||||||
|
@ -209,7 +218,7 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
|
|
||||||
processEnabledIcons()
|
processEnabledIcons()
|
||||||
|
|
||||||
binding.correctionPercent.setOnCheckedChangeListener {_, isChecked ->
|
binding.correctionPercent.setOnCheckedChangeListener { _, isChecked ->
|
||||||
run {
|
run {
|
||||||
sp.putBoolean(rh.gs(R.string.key_wizard_correction_percent), isChecked)
|
sp.putBoolean(rh.gs(R.string.key_wizard_correction_percent), isChecked)
|
||||||
binding.correctionUnit.text = if (isChecked) "%" else rh.gs(R.string.insulin_unit_shortname)
|
binding.correctionUnit.text = if (isChecked) "%" else rh.gs(R.string.insulin_unit_shortname)
|
||||||
|
@ -228,35 +237,21 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
binding.correctionInput.value = if (correctionPercent) calculatedPercentage else Round.roundTo(calculatedCorrection, bolusStep)
|
binding.correctionInput.value = if (correctionPercent) calculatedPercentage else Round.roundTo(calculatedCorrection, bolusStep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// profile spinner
|
// profile
|
||||||
binding.profile.onItemSelectedListener = object : OnItemSelectedListener {
|
binding.profileList.onItemClickListener = AdapterView.OnItemClickListener { _, _, _, _ -> calculateInsulin() }
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
|
||||||
ToastUtils.showToastInUiThread(ctx, rh.gs(R.string.noprofileset))
|
|
||||||
binding.okcancel.ok.visibility = View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
|
||||||
calculateInsulin()
|
|
||||||
binding.okcancel.ok.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// bus
|
// bus
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({
|
.subscribe({ calculateInsulin() }, fabricPrivacy::logException)
|
||||||
activity?.runOnUiThread { calculateInsulin() }
|
|
||||||
}, fabricPrivacy::logException)
|
|
||||||
)
|
|
||||||
|
|
||||||
setA11yLabels()
|
setA11yLabels()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setA11yLabels() {
|
private fun setA11yLabels() {
|
||||||
binding.bgInput.editText?.id?.let { binding.bgInputLabel.labelFor = it }
|
binding.bgInputLabel.labelFor = binding.bgInput.editTextId
|
||||||
binding.carbsInput.editText?.id?.let { binding.carbsInputLabel.labelFor = it }
|
binding.carbsInputLabel.labelFor = binding.carbsInput.editTextId
|
||||||
binding.correctionInput.editText?.id?.let { binding.correctionInputLabel.labelFor = it }
|
binding.correctionInputLabel.labelFor = binding.correctionInput.editTextId
|
||||||
binding.carbTimeInput.editText?.id?.let { binding.carbTimeInputLabel.labelFor = it }
|
binding.carbTimeInputLabel.labelFor = binding.carbTimeInput.editTextId
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
|
@ -307,6 +302,7 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
binding.trendCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
|
binding.trendCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
|
||||||
binding.iobCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
|
binding.iobCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
|
||||||
binding.cobCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
|
binding.cobCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
|
||||||
|
binding.checkboxRow.visibility = binding.calculationCheckbox.isChecked.not().toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveCheckedStates() {
|
private fun saveCheckedStates() {
|
||||||
|
@ -318,7 +314,7 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
private fun loadCheckedStates() {
|
private fun loadCheckedStates() {
|
||||||
binding.bgTrendCheckbox.isChecked = sp.getBoolean(R.string.key_wizard_include_trend_bg, false)
|
binding.bgTrendCheckbox.isChecked = sp.getBoolean(R.string.key_wizard_include_trend_bg, false)
|
||||||
binding.cobCheckbox.isChecked = sp.getBoolean(R.string.key_wizard_include_cob, false)
|
binding.cobCheckbox.isChecked = sp.getBoolean(R.string.key_wizard_include_cob, false)
|
||||||
correctionPercent = sp.getBoolean(R.string.key_wizard_correction_percent,false)
|
correctionPercent = sp.getBoolean(R.string.key_wizard_correction_percent, false)
|
||||||
binding.correctionPercent.isChecked = correctionPercent
|
binding.correctionPercent.isChecked = correctionPercent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,11 +323,11 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
else DecimalFormatter.to1Decimal(value * Constants.MGDL_TO_MMOLL)
|
else DecimalFormatter.to1Decimal(value * Constants.MGDL_TO_MMOLL)
|
||||||
|
|
||||||
private fun initDialog() {
|
private fun initDialog() {
|
||||||
if(carbsPassedIntoWizard != 0.0) {
|
if (carbsPassedIntoWizard != 0.0) {
|
||||||
binding.carbsInput.value = carbsPassedIntoWizard
|
binding.carbsInput.value = carbsPassedIntoWizard
|
||||||
}
|
}
|
||||||
if(notesPassedIntoWizard.isNotBlank()) {
|
if (notesPassedIntoWizard.isNotBlank()) {
|
||||||
binding.notes.setText(notesPassedIntoWizard)
|
binding.notesLayout.notes.setText(notesPassedIntoWizard)
|
||||||
}
|
}
|
||||||
val profile = profileFunction.getProfile()
|
val profile = profileFunction.getProfile()
|
||||||
val profileStore = activePlugin.activeProfileSource.profile
|
val profileStore = activePlugin.activeProfileSource.profile
|
||||||
|
@ -345,9 +341,9 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
val profileList: ArrayList<CharSequence> = profileStore.getProfileList()
|
val profileList: ArrayList<CharSequence> = profileStore.getProfileList()
|
||||||
profileList.add(0, rh.gs(R.string.active))
|
profileList.add(0, rh.gs(R.string.active))
|
||||||
context?.let { context ->
|
context?.let { context ->
|
||||||
val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList)
|
binding.profileList.setAdapter(ArrayAdapter(context, R.layout.spinner_centered, profileList))
|
||||||
binding.profile.adapter = adapter
|
binding.profileList.setText(profileList[0], false)
|
||||||
} ?: return
|
}
|
||||||
|
|
||||||
val units = profileFunction.getUnits()
|
val units = profileFunction.getUnits()
|
||||||
binding.bgUnits.text = units.asText
|
binding.bgUnits.text = units.asText
|
||||||
|
@ -370,11 +366,10 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
binding.percentUsed.visibility = (sp.getInt(R.string.key_boluswizard_percentage, 100) != 100 || correctionPercent).toVisibility()
|
binding.percentUsed.visibility = (sp.getInt(R.string.key_boluswizard_percentage, 100) != 100 || correctionPercent).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
private fun calculateInsulin() {
|
private fun calculateInsulin() {
|
||||||
val profileStore = activePlugin.activeProfileSource.profile
|
val profileStore = activePlugin.activeProfileSource.profile ?: return // not initialized yet
|
||||||
if (binding.profile.selectedItem == null || profileStore == null)
|
var profileName = binding.profileList.text.toString()
|
||||||
return // not initialized yet
|
|
||||||
var profileName = binding.profile.selectedItem.toString()
|
|
||||||
val specificProfile: Profile?
|
val specificProfile: Profile?
|
||||||
if (profileName == rh.gs(R.string.active)) {
|
if (profileName == rh.gs(R.string.active)) {
|
||||||
specificProfile = profileFunction.getProfile()
|
specificProfile = profileFunction.getProfile()
|
||||||
|
@ -396,7 +391,7 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
} else
|
} else
|
||||||
0.0
|
0.0
|
||||||
val percentageCorrection = if (usePercentage) {
|
val percentageCorrection = if (usePercentage) {
|
||||||
if (Round.roundTo(calculatedPercentage,1.0) == SafeParse.stringToDouble(binding.correctionInput.text))
|
if (Round.roundTo(calculatedPercentage, 1.0) == SafeParse.stringToDouble(binding.correctionInput.text))
|
||||||
calculatedPercentage
|
calculatedPercentage
|
||||||
else
|
else
|
||||||
SafeParse.stringToDouble(binding.correctionInput.text)
|
SafeParse.stringToDouble(binding.correctionInput.text)
|
||||||
|
@ -422,7 +417,8 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
|
|
||||||
val carbTime = SafeParse.stringToInt(binding.carbTimeInput.text)
|
val carbTime = SafeParse.stringToInt(binding.carbTimeInput.text)
|
||||||
|
|
||||||
wizard = BolusWizard(injector).doCalc(specificProfile, profileName, tempTarget, carbsAfterConstraint, cob, bg, correction, sp.getInt(R.string.key_boluswizard_percentage, 100),
|
wizard = BolusWizard(injector).doCalc(
|
||||||
|
specificProfile, profileName, tempTarget, carbsAfterConstraint, cob, bg, correction, sp.getInt(R.string.key_boluswizard_percentage, 100),
|
||||||
binding.bgCheckbox.isChecked,
|
binding.bgCheckbox.isChecked,
|
||||||
binding.cobCheckbox.isChecked,
|
binding.cobCheckbox.isChecked,
|
||||||
binding.iobCheckbox.isChecked,
|
binding.iobCheckbox.isChecked,
|
||||||
|
@ -431,17 +427,17 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
binding.ttCheckbox.isChecked,
|
binding.ttCheckbox.isChecked,
|
||||||
binding.bgTrendCheckbox.isChecked,
|
binding.bgTrendCheckbox.isChecked,
|
||||||
binding.alarm.isChecked,
|
binding.alarm.isChecked,
|
||||||
binding.notes.text.toString(),
|
binding.notesLayout.notes.text.toString(),
|
||||||
carbTime,
|
carbTime,
|
||||||
usePercentage = usePercentage,
|
usePercentage = usePercentage,
|
||||||
totalPercentage = percentageCorrection
|
totalPercentage = percentageCorrection
|
||||||
)
|
)
|
||||||
|
|
||||||
wizard?.let { wizard ->
|
wizard?.let { wizard ->
|
||||||
binding.bg.text = String.format(rh.gs(R.string.format_bg_isf), valueToUnitsToString(Profile.toMgdl(bg, profileFunction.getUnits()), profileFunction.getUnits().asText), wizard.sens)
|
binding.bg.text = rh.gs(R.string.format_bg_isf, valueToUnitsToString(Profile.toMgdl(bg, profileFunction.getUnits()), profileFunction.getUnits().asText), wizard.sens)
|
||||||
binding.bgInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromBG)
|
binding.bgInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromBG)
|
||||||
|
|
||||||
binding.carbs.text = String.format(rh.gs(R.string.format_carbs_ic), carbs.toDouble(), wizard.ic)
|
binding.carbs.text = rh.gs(R.string.format_carbs_ic, carbs.toDouble(), wizard.ic)
|
||||||
binding.carbsInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromCarbs)
|
binding.carbsInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromCarbs)
|
||||||
|
|
||||||
binding.iobInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromBolusIOB + wizard.insulinFromBasalIOB)
|
binding.iobInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromBolusIOB + wizard.insulinFromBasalIOB)
|
||||||
|
@ -464,7 +460,7 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
|
|
||||||
// COB
|
// COB
|
||||||
if (binding.cobCheckbox.isChecked) {
|
if (binding.cobCheckbox.isChecked) {
|
||||||
binding.cob.text = String.format(rh.gs(R.string.format_cob_ic), cob, wizard.ic)
|
binding.cob.text = rh.gs(R.string.format_cob_ic, cob, wizard.ic)
|
||||||
binding.cobInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromCOB)
|
binding.cobInsulin.text = rh.gs(R.string.formatinsulinunits, wizard.insulinFromCOB)
|
||||||
} else {
|
} else {
|
||||||
binding.cob.text = ""
|
binding.cob.text = ""
|
||||||
|
@ -472,12 +468,12 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wizard.calculatedTotalInsulin > 0.0 || carbsAfterConstraint > 0.0) {
|
if (wizard.calculatedTotalInsulin > 0.0 || carbsAfterConstraint > 0.0) {
|
||||||
val insulinText = if (wizard.calculatedTotalInsulin > 0.0) rh.gs(R.string.formatinsulinunits, wizard.calculatedTotalInsulin).formatColor(rh, R.color.bolus) else ""
|
val insulinText = if (wizard.calculatedTotalInsulin > 0.0) rh.gs(R.string.formatinsulinunits, wizard.calculatedTotalInsulin).formatColor(context, rh, R.attr.bolusColor) else ""
|
||||||
val carbsText = if (carbsAfterConstraint > 0.0) rh.gs(R.string.format_carbs, carbsAfterConstraint).formatColor(rh, R.color.carbs) else ""
|
val carbsText = if (carbsAfterConstraint > 0.0) rh.gs(R.string.format_carbs, carbsAfterConstraint).formatColor(context, rh, R.attr.carbsColor) else ""
|
||||||
binding.total.text = HtmlHelper.fromHtml(rh.gs(R.string.result_insulin_carbs, insulinText, carbsText))
|
binding.total.text = HtmlHelper.fromHtml(rh.gs(R.string.result_insulin_carbs, insulinText, carbsText))
|
||||||
binding.okcancel.ok.visibility = View.VISIBLE
|
binding.okcancel.ok.visibility = View.VISIBLE
|
||||||
} else {
|
} else {
|
||||||
binding.total.text = HtmlHelper.fromHtml(rh.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt()).formatColor(rh, R.color.carbs))
|
binding.total.text = HtmlHelper.fromHtml(rh.gs(R.string.missing_carbs, wizard.carbsEquivalent.toInt()).formatColor(context, rh, R.attr.carbsColor))
|
||||||
binding.okcancel.ok.visibility = View.INVISIBLE
|
binding.okcancel.ok.visibility = View.INVISIBLE
|
||||||
}
|
}
|
||||||
binding.percentUsed.text = rh.gs(R.string.format_percent, wizard.percentageCorrection)
|
binding.percentUsed.text = rh.gs(R.string.format_percent, wizard.percentageCorrection)
|
||||||
|
@ -497,4 +493,20 @@ class WizardDialog : DaggerDialogFragment() {
|
||||||
aapsLogger.debug(e.localizedMessage ?: "")
|
aapsLogger.debug(e.localizedMessage ?: "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if(!queryingProtection) {
|
||||||
|
queryingProtection = true
|
||||||
|
activity?.let { activity ->
|
||||||
|
val cancelFail = {
|
||||||
|
queryingProtection = false
|
||||||
|
aapsLogger.debug(LTag.APS, "Dialog canceled on resume protection: ${this.javaClass.name}")
|
||||||
|
ToastUtils.showToastInUiThread(ctx, R.string.dialog_canceled)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
protectionCheck.queryProtection(activity, BOLUS, { queryingProtection = false }, cancelFail, cancelFail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
package info.nightscout.androidaps.events
|
|
||||||
|
|
||||||
class EventReloadProfileSwitchData : Event()
|
|
|
@ -1,3 +0,0 @@
|
||||||
package info.nightscout.androidaps.events
|
|
||||||
|
|
||||||
class EventTreatmentUpdateGui : EventUpdateGui()
|
|
|
@ -1,5 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.aps.events
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event
|
|
||||||
|
|
||||||
class EventLoopInvoked : Event()
|
|
|
@ -10,11 +10,13 @@ import android.content.Intent
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.*
|
import info.nightscout.androidaps.BuildConfig
|
||||||
|
import info.nightscout.androidaps.Constants
|
||||||
|
import info.nightscout.androidaps.MainActivity
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||||
import info.nightscout.androidaps.annotations.OpenForTesting
|
import info.nightscout.androidaps.annotations.OpenForTesting
|
||||||
import info.nightscout.androidaps.data.DetailedBolusInfo
|
import info.nightscout.androidaps.data.DetailedBolusInfo
|
||||||
import info.nightscout.androidaps.interfaces.Profile
|
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult
|
import info.nightscout.androidaps.data.PumpEnactResult
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.database.ValueWrapper
|
import info.nightscout.androidaps.database.ValueWrapper
|
||||||
|
@ -25,13 +27,13 @@ import info.nightscout.androidaps.database.entities.ValueWithUnit
|
||||||
import info.nightscout.androidaps.database.transactions.InsertAndCancelCurrentOfflineEventTransaction
|
import info.nightscout.androidaps.database.transactions.InsertAndCancelCurrentOfflineEventTransaction
|
||||||
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
|
import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction
|
||||||
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange
|
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange
|
||||||
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
|
||||||
import info.nightscout.androidaps.events.EventNewBG
|
|
||||||
import info.nightscout.androidaps.events.EventTempTargetChange
|
import info.nightscout.androidaps.events.EventTempTargetChange
|
||||||
|
import info.nightscout.androidaps.extensions.buildDeviceStatus
|
||||||
|
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
||||||
|
import info.nightscout.androidaps.extensions.convertedToPercent
|
||||||
|
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
import info.nightscout.androidaps.interfaces.Loop.LastRun
|
import info.nightscout.androidaps.interfaces.Loop.LastRun
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui
|
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui
|
import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui
|
||||||
|
@ -51,13 +53,10 @@ import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.HardLimits
|
import info.nightscout.androidaps.utils.HardLimits
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.extensions.buildDeviceStatus
|
|
||||||
import info.nightscout.androidaps.extensions.convertedToAbsolute
|
|
||||||
import info.nightscout.androidaps.extensions.convertedToPercent
|
|
||||||
import info.nightscout.androidaps.extensions.plannedRemainingMinutes
|
|
||||||
import info.nightscout.androidaps.plugins.aps.events.EventLoopInvoked
|
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
@ -88,20 +87,21 @@ class LoopPlugin @Inject constructor(
|
||||||
private val uel: UserEntryLogger,
|
private val uel: UserEntryLogger,
|
||||||
private val repository: AppRepository,
|
private val repository: AppRepository,
|
||||||
private val runningConfiguration: RunningConfiguration
|
private val runningConfiguration: RunningConfiguration
|
||||||
) : PluginBase(PluginDescription()
|
) : PluginBase(
|
||||||
.mainType(PluginType.LOOP)
|
PluginDescription()
|
||||||
.fragmentClass(LoopFragment::class.java.name)
|
.mainType(PluginType.LOOP)
|
||||||
.pluginIcon(R.drawable.ic_loop_closed_white)
|
.fragmentClass(LoopFragment::class.java.name)
|
||||||
.pluginName(R.string.loop)
|
.pluginIcon(R.drawable.ic_loop_closed_white)
|
||||||
.shortName(R.string.loop_shortname)
|
.pluginName(R.string.loop)
|
||||||
.preferencesId(R.xml.pref_loop)
|
.shortName(R.string.loop_shortname)
|
||||||
.enableByDefault(config.APS)
|
.preferencesId(R.xml.pref_loop)
|
||||||
.description(R.string.description_loop),
|
.enableByDefault(config.APS)
|
||||||
|
.description(R.string.description_loop),
|
||||||
aapsLogger, rh, injector
|
aapsLogger, rh, injector
|
||||||
), Loop {
|
), Loop {
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
private var lastBgTriggeredRun: Long = 0
|
override var lastBgTriggeredRun: Long = 0
|
||||||
private var carbsSuggestionsSuspendedUntil: Long = 0
|
private var carbsSuggestionsSuspendedUntil: Long = 0
|
||||||
private var prevCarbsreq = 0
|
private var prevCarbsreq = 0
|
||||||
override var lastRun: LastRun? = null
|
override var lastRun: LastRun? = null
|
||||||
|
@ -109,39 +109,19 @@ class LoopPlugin @Inject constructor(
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
createNotificationChannel()
|
createNotificationChannel()
|
||||||
super.onStart()
|
super.onStart()
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventTempTargetChange::class.java)
|
.toObservable(EventTempTargetChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ invoke("EventTempTargetChange", true) }, fabricPrivacy::logException)
|
.subscribe({ invoke("EventTempTargetChange", true) }, fabricPrivacy::logException)
|
||||||
)
|
|
||||||
/*
|
|
||||||
This method is triggered once autosens calculation has completed, so the LoopPlugin
|
|
||||||
has current data to work with. However, autosens calculation can be triggered by multiple
|
|
||||||
sources and currently only a new BG should trigger a loop run. Hence we return early if
|
|
||||||
the event causing the calculation is not EventNewBg.
|
|
||||||
<p>
|
|
||||||
*/
|
|
||||||
disposable.add(rxBus
|
|
||||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ event: EventAutosensCalculationFinished ->
|
|
||||||
// Autosens calculation not triggered by a new BG
|
|
||||||
if (event.cause !is EventNewBG) return@subscribe
|
|
||||||
val glucoseValue = iobCobCalculator.ads.actualBg() ?: return@subscribe
|
|
||||||
// BG outdated
|
|
||||||
// already looped with that value
|
|
||||||
if (glucoseValue.timestamp <= lastBgTriggeredRun) return@subscribe
|
|
||||||
lastBgTriggeredRun = glucoseValue.timestamp
|
|
||||||
invoke("AutosenseCalculation for $glucoseValue", true)
|
|
||||||
}, fabricPrivacy::logException)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createNotificationChannel() {
|
private fun createNotificationChannel() {
|
||||||
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
val mNotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
@SuppressLint("WrongConstant") val channel = NotificationChannel(CHANNEL_ID,
|
@SuppressLint("WrongConstant") val channel = NotificationChannel(
|
||||||
CHANNEL_ID,
|
CHANNEL_ID,
|
||||||
NotificationManager.IMPORTANCE_HIGH)
|
CHANNEL_ID,
|
||||||
|
NotificationManager.IMPORTANCE_HIGH
|
||||||
|
)
|
||||||
mNotificationManager.createNotificationChannel(channel)
|
mNotificationManager.createNotificationChannel(channel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +235,7 @@ class LoopPlugin @Inject constructor(
|
||||||
if (apsResult == null) {
|
if (apsResult == null) {
|
||||||
rxBus.send(EventLoopSetLastRunGui(rh.gs(R.string.noapsselected)))
|
rxBus.send(EventLoopSetLastRunGui(rh.gs(R.string.noapsselected)))
|
||||||
return
|
return
|
||||||
} else rxBus.send(EventLoopInvoked())
|
}
|
||||||
|
|
||||||
if (!isEmptyQueue()) {
|
if (!isEmptyQueue()) {
|
||||||
aapsLogger.debug(LTag.APS, rh.gs(R.string.pumpbusy))
|
aapsLogger.debug(LTag.APS, rh.gs(R.string.pumpbusy))
|
||||||
|
@ -296,9 +276,11 @@ class LoopPlugin @Inject constructor(
|
||||||
lastRun.lastTBRRequest = 0
|
lastRun.lastTBRRequest = 0
|
||||||
lastRun.lastSMBEnact = 0
|
lastRun.lastSMBEnact = 0
|
||||||
lastRun.lastSMBRequest = 0
|
lastRun.lastSMBRequest = 0
|
||||||
buildDeviceStatus(dateUtil, this, iobCobCalculator, profileFunction,
|
buildDeviceStatus(
|
||||||
|
dateUtil, this, iobCobCalculator, profileFunction,
|
||||||
activePlugin.activePump, receiverStatusStore, runningConfiguration,
|
activePlugin.activePump, receiverStatusStore, runningConfiguration,
|
||||||
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
|
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION
|
||||||
|
)?.also {
|
||||||
repository.insert(it)
|
repository.insert(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +298,11 @@ class LoopPlugin @Inject constructor(
|
||||||
if (closedLoopEnabled.value()) {
|
if (closedLoopEnabled.value()) {
|
||||||
if (allowNotification) {
|
if (allowNotification) {
|
||||||
if (resultAfterConstraints.isCarbsRequired
|
if (resultAfterConstraints.isCarbsRequired
|
||||||
&& resultAfterConstraints.carbsReq >= sp.getInt(R.string.key_smb_enable_carbs_suggestions_threshold, 0) && carbsSuggestionsSuspendedUntil < System.currentTimeMillis() && !treatmentTimeThreshold(-15)) {
|
&& resultAfterConstraints.carbsReq >= sp.getInt(
|
||||||
|
R.string.key_smb_enable_carbs_suggestions_threshold,
|
||||||
|
0
|
||||||
|
) && carbsSuggestionsSuspendedUntil < System.currentTimeMillis() && !treatmentTimeThreshold(-15)
|
||||||
|
) {
|
||||||
if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local, true) && !sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
|
if (sp.getBoolean(R.string.key_enable_carbs_required_alert_local, true) && !sp.getBoolean(R.string.key_raise_notifications_as_android_notifications, true)) {
|
||||||
val carbReqLocal = Notification(Notification.CARBS_REQUIRED, resultAfterConstraints.carbsRequiredText, Notification.NORMAL)
|
val carbReqLocal = Notification(Notification.CARBS_REQUIRED, resultAfterConstraints.carbsRequiredText, Notification.NORMAL)
|
||||||
rxBus.send(EventNewNotification(carbReqLocal))
|
rxBus.send(EventNewNotification(carbReqLocal))
|
||||||
|
@ -353,9 +339,11 @@ class LoopPlugin @Inject constructor(
|
||||||
|
|
||||||
// mId allows you to update the notification later on.
|
// mId allows you to update the notification later on.
|
||||||
mNotificationManager.notify(Constants.notificationID, builder.build())
|
mNotificationManager.notify(Constants.notificationID, builder.build())
|
||||||
uel.log(Action.CAREPORTAL, Sources.Loop, rh.gs(R.string.carbsreq, resultAfterConstraints.carbsReq, resultAfterConstraints.carbsReqWithin),
|
uel.log(
|
||||||
ValueWithUnit.Gram(resultAfterConstraints.carbsReq),
|
Action.CAREPORTAL, Sources.Loop, rh.gs(R.string.carbsreq, resultAfterConstraints.carbsReq, resultAfterConstraints.carbsReqWithin),
|
||||||
ValueWithUnit.Minute(resultAfterConstraints.carbsReqWithin))
|
ValueWithUnit.Gram(resultAfterConstraints.carbsReq),
|
||||||
|
ValueWithUnit.Minute(resultAfterConstraints.carbsReqWithin)
|
||||||
|
)
|
||||||
rxBus.send(EventNewOpenLoopNotification())
|
rxBus.send(EventNewOpenLoopNotification())
|
||||||
|
|
||||||
//only send to wear if Native notifications are turned off
|
//only send to wear if Native notifications are turned off
|
||||||
|
@ -373,7 +361,8 @@ class LoopPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (resultAfterConstraints.isChangeRequested
|
if (resultAfterConstraints.isChangeRequested
|
||||||
&& !commandQueue.bolusInQueue()) {
|
&& !commandQueue.bolusInQueue()
|
||||||
|
) {
|
||||||
val waiting = PumpEnactResult(injector)
|
val waiting = PumpEnactResult(injector)
|
||||||
waiting.queued = true
|
waiting.queued = true
|
||||||
if (resultAfterConstraints.tempBasalRequested) lastRun.tbrSetByPump = waiting
|
if (resultAfterConstraints.tempBasalRequested) lastRun.tbrSetByPump = waiting
|
||||||
|
@ -486,9 +475,11 @@ class LoopPlugin @Inject constructor(
|
||||||
lastRun.lastTBRRequest = lastRun.lastAPSRun
|
lastRun.lastTBRRequest = lastRun.lastAPSRun
|
||||||
lastRun.lastTBREnact = dateUtil.now()
|
lastRun.lastTBREnact = dateUtil.now()
|
||||||
lastRun.lastOpenModeAccept = dateUtil.now()
|
lastRun.lastOpenModeAccept = dateUtil.now()
|
||||||
buildDeviceStatus(dateUtil, this@LoopPlugin, iobCobCalculator, profileFunction,
|
buildDeviceStatus(
|
||||||
|
dateUtil, this@LoopPlugin, iobCobCalculator, profileFunction,
|
||||||
activePlugin.activePump, receiverStatusStore, runningConfiguration,
|
activePlugin.activePump, receiverStatusStore, runningConfiguration,
|
||||||
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION)?.also {
|
BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION
|
||||||
|
)?.also {
|
||||||
repository.insert(it)
|
repository.insert(it)
|
||||||
}
|
}
|
||||||
sp.incInt(R.string.key_ObjectivesmanualEnacts)
|
sp.incInt(R.string.key_ObjectivesmanualEnacts)
|
||||||
|
@ -531,8 +522,10 @@ class LoopPlugin @Inject constructor(
|
||||||
commandQueue.cancelTempBasal(false, callback)
|
commandQueue.cancelTempBasal(false, callback)
|
||||||
} else {
|
} else {
|
||||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: Basal set correctly")
|
aapsLogger.debug(LTag.APS, "applyAPSRequest: Basal set correctly")
|
||||||
callback?.result(PumpEnactResult(injector).absolute(request.rate).duration(0)
|
callback?.result(
|
||||||
.enacted(false).success(true).comment(R.string.basal_set_correctly))?.run()
|
PumpEnactResult(injector).absolute(request.rate).duration(0)
|
||||||
|
.enacted(false).success(true).comment(R.string.basal_set_correctly)
|
||||||
|
)?.run()
|
||||||
}
|
}
|
||||||
} else if (request.usePercent && allowPercentage()) {
|
} else if (request.usePercent && allowPercentage()) {
|
||||||
if (request.percent == 100 && request.duration == 0) {
|
if (request.percent == 100 && request.duration == 0) {
|
||||||
|
@ -542,32 +535,52 @@ class LoopPlugin @Inject constructor(
|
||||||
commandQueue.cancelTempBasal(false, callback)
|
commandQueue.cancelTempBasal(false, callback)
|
||||||
} else {
|
} else {
|
||||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: Basal set correctly")
|
aapsLogger.debug(LTag.APS, "applyAPSRequest: Basal set correctly")
|
||||||
callback?.result(PumpEnactResult(injector).percent(request.percent).duration(0)
|
callback?.result(
|
||||||
.enacted(false).success(true).comment(R.string.basal_set_correctly))?.run()
|
PumpEnactResult(injector).percent(request.percent).duration(0)
|
||||||
|
.enacted(false).success(true).comment(R.string.basal_set_correctly)
|
||||||
|
)?.run()
|
||||||
}
|
}
|
||||||
} else if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && request.percent == activeTemp.convertedToPercent(now, profile)) {
|
} else if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && request.percent == activeTemp.convertedToPercent(
|
||||||
|
now,
|
||||||
|
profile
|
||||||
|
)
|
||||||
|
) {
|
||||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly")
|
aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly")
|
||||||
callback?.result(PumpEnactResult(injector).percent(request.percent)
|
callback?.result(
|
||||||
.enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes)
|
PumpEnactResult(injector).percent(request.percent)
|
||||||
.comment(R.string.let_temp_basal_run))?.run()
|
.enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes)
|
||||||
|
.comment(R.string.let_temp_basal_run)
|
||||||
|
)?.run()
|
||||||
} else {
|
} else {
|
||||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: tempBasalPercent()")
|
aapsLogger.debug(LTag.APS, "applyAPSRequest: tempBasalPercent()")
|
||||||
uel.log(Action.TEMP_BASAL, Sources.Loop,
|
uel.log(
|
||||||
|
Action.TEMP_BASAL, Sources.Loop,
|
||||||
ValueWithUnit.Percent(request.percent),
|
ValueWithUnit.Percent(request.percent),
|
||||||
ValueWithUnit.Minute(request.duration))
|
ValueWithUnit.Minute(request.duration)
|
||||||
|
)
|
||||||
commandQueue.tempBasalPercent(request.percent, request.duration, false, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
|
commandQueue.tempBasalPercent(request.percent, request.duration, false, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && abs(request.rate - activeTemp.convertedToAbsolute(now, profile)) < pump.pumpDescription.basalStep) {
|
if (activeTemp != null && activeTemp.plannedRemainingMinutes > 5 && request.duration - activeTemp.plannedRemainingMinutes < 30 && abs(
|
||||||
|
request.rate - activeTemp.convertedToAbsolute(
|
||||||
|
now,
|
||||||
|
profile
|
||||||
|
)
|
||||||
|
) < pump.pumpDescription.basalStep
|
||||||
|
) {
|
||||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly")
|
aapsLogger.debug(LTag.APS, "applyAPSRequest: Temp basal set correctly")
|
||||||
callback?.result(PumpEnactResult(injector).absolute(activeTemp.convertedToAbsolute(now, profile))
|
callback?.result(
|
||||||
.enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes)
|
PumpEnactResult(injector).absolute(activeTemp.convertedToAbsolute(now, profile))
|
||||||
.comment(R.string.let_temp_basal_run))?.run()
|
.enacted(false).success(true).duration(activeTemp.plannedRemainingMinutes)
|
||||||
|
.comment(R.string.let_temp_basal_run)
|
||||||
|
)?.run()
|
||||||
} else {
|
} else {
|
||||||
aapsLogger.debug(LTag.APS, "applyAPSRequest: setTempBasalAbsolute()")
|
aapsLogger.debug(LTag.APS, "applyAPSRequest: setTempBasalAbsolute()")
|
||||||
uel.log(Action.TEMP_BASAL, Sources.Loop,
|
uel.log(
|
||||||
|
Action.TEMP_BASAL, Sources.Loop,
|
||||||
ValueWithUnit.UnitPerHour(request.rate),
|
ValueWithUnit.UnitPerHour(request.rate),
|
||||||
ValueWithUnit.Minute(request.duration))
|
ValueWithUnit.Minute(request.duration)
|
||||||
|
)
|
||||||
commandQueue.tempBasalAbsolute(request.rate, request.duration, false, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
|
commandQueue.tempBasalAbsolute(request.rate, request.duration, false, profile, PumpSync.TemporaryBasalType.NORMAL, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -581,9 +594,11 @@ class LoopPlugin @Inject constructor(
|
||||||
val lastBolusTime = repository.getLastBolusRecord()?.timestamp ?: 0L
|
val lastBolusTime = repository.getLastBolusRecord()?.timestamp ?: 0L
|
||||||
if (lastBolusTime != 0L && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) {
|
if (lastBolusTime != 0L && lastBolusTime + 3 * 60 * 1000 > System.currentTimeMillis()) {
|
||||||
aapsLogger.debug(LTag.APS, "SMB requested but still in 3 min interval")
|
aapsLogger.debug(LTag.APS, "SMB requested but still in 3 min interval")
|
||||||
callback?.result(PumpEnactResult(injector)
|
callback?.result(
|
||||||
.comment(R.string.smb_frequency_exceeded)
|
PumpEnactResult(injector)
|
||||||
.enacted(false).success(false))?.run()
|
.comment(R.string.smb_frequency_exceeded)
|
||||||
|
.enacted(false).success(false)
|
||||||
|
)?.run()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!pump.isInitialized()) {
|
if (!pump.isInitialized()) {
|
||||||
|
@ -619,11 +634,11 @@ class LoopPlugin @Inject constructor(
|
||||||
val pump = activePlugin.activePump
|
val pump = activePlugin.activePump
|
||||||
disposable += repository.runTransactionForResult(InsertAndCancelCurrentOfflineEventTransaction(dateUtil.now(), T.mins(durationInMinutes.toLong()).msecs(), reason))
|
disposable += repository.runTransactionForResult(InsertAndCancelCurrentOfflineEventTransaction(dateUtil.now(), T.mins(durationInMinutes.toLong()).msecs(), reason))
|
||||||
.subscribe({ result ->
|
.subscribe({ result ->
|
||||||
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated OfflineEvent $it") }
|
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated OfflineEvent $it") }
|
||||||
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted OfflineEvent $it") }
|
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted OfflineEvent $it") }
|
||||||
}, {
|
}, {
|
||||||
aapsLogger.error(LTag.DATABASE, "Error while saving OfflineEvent", it)
|
aapsLogger.error(LTag.DATABASE, "Error while saving OfflineEvent", it)
|
||||||
})
|
})
|
||||||
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
|
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
|
||||||
commandQueue.tempBasalAbsolute(0.0, durationInMinutes, true, profile, PumpSync.TemporaryBasalType.EMULATED_PUMP_SUSPEND, object : Callback() {
|
commandQueue.tempBasalAbsolute(0.0, durationInMinutes, true, profile, PumpSync.TemporaryBasalType.EMULATED_PUMP_SUSPEND, object : Callback() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -655,11 +670,11 @@ class LoopPlugin @Inject constructor(
|
||||||
override fun suspendLoop(durationInMinutes: Int) {
|
override fun suspendLoop(durationInMinutes: Int) {
|
||||||
disposable += repository.runTransactionForResult(InsertAndCancelCurrentOfflineEventTransaction(dateUtil.now(), T.mins(durationInMinutes.toLong()).msecs(), OfflineEvent.Reason.SUSPEND))
|
disposable += repository.runTransactionForResult(InsertAndCancelCurrentOfflineEventTransaction(dateUtil.now(), T.mins(durationInMinutes.toLong()).msecs(), OfflineEvent.Reason.SUSPEND))
|
||||||
.subscribe({ result ->
|
.subscribe({ result ->
|
||||||
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated OfflineEvent $it") }
|
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated OfflineEvent $it") }
|
||||||
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted OfflineEvent $it") }
|
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted OfflineEvent $it") }
|
||||||
}, {
|
}, {
|
||||||
aapsLogger.error(LTag.DATABASE, "Error while saving OfflineEvent", it)
|
aapsLogger.error(LTag.DATABASE, "Error while saving OfflineEvent", it)
|
||||||
})
|
})
|
||||||
commandQueue.cancelTempBasal(true, object : Callback() {
|
commandQueue.cancelTempBasal(true, object : Callback() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
|
|
|
@ -51,7 +51,7 @@ class DetermineBasalResultSMB private constructor(injector: HasAndroidInjector)
|
||||||
aapsLogger.error(LTag.APS, "Error parsing 'deliverAt' date: $date", e)
|
aapsLogger.error(LTag.APS, "Error parsing 'deliverAt' date: $date", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result.has("variable_sens")) variableSens = result.getDouble("variable_sens");
|
if (result.has("variable_sens")) variableSens = result.getDouble("variable_sens")
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
aapsLogger.error(LTag.APS, "Error parsing determine-basal result JSON", e)
|
aapsLogger.error(LTag.APS, "Error parsing determine-basal result JSON", e)
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,9 +194,9 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri
|
||||||
this.profile.put("current_basal_safety_multiplier", sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0))
|
this.profile.put("current_basal_safety_multiplier", sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0))
|
||||||
|
|
||||||
//mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity));
|
//mProfile.put("high_temptarget_raises_sensitivity", SP.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity));
|
||||||
this.profile.put("high_temptarget_raises_sensitivity", false)
|
this.profile.put("high_temptarget_raises_sensitivity", sp.getBoolean(R.string.key_high_temptarget_raises_sensitivity, SMBDefaults.high_temptarget_raises_sensitivity))
|
||||||
//mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity));
|
//mProfile.put("low_temptarget_lowers_sensitivity", SP.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity));
|
||||||
this.profile.put("low_temptarget_lowers_sensitivity", false)
|
this.profile.put("low_temptarget_lowers_sensitivity", sp.getBoolean(R.string.key_low_temptarget_lowers_sensitivity, SMBDefaults.low_temptarget_lowers_sensitivity))
|
||||||
this.profile.put("sensitivity_raises_target", sp.getBoolean(R.string.key_sensitivity_raises_target, SMBDefaults.sensitivity_raises_target))
|
this.profile.put("sensitivity_raises_target", sp.getBoolean(R.string.key_sensitivity_raises_target, SMBDefaults.sensitivity_raises_target))
|
||||||
this.profile.put("resistance_lowers_target", sp.getBoolean(R.string.key_resistance_lowers_target, SMBDefaults.resistance_lowers_target))
|
this.profile.put("resistance_lowers_target", sp.getBoolean(R.string.key_resistance_lowers_target, SMBDefaults.resistance_lowers_target))
|
||||||
this.profile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments)
|
this.profile.put("adv_target_adjustments", SMBDefaults.adv_target_adjustments)
|
||||||
|
@ -222,12 +222,17 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri
|
||||||
this.profile.put("enableSMB_after_carbs", smbEnabled && sp.getBoolean(R.string.key_enableSMB_after_carbs, false) && advancedFiltering)
|
this.profile.put("enableSMB_after_carbs", smbEnabled && sp.getBoolean(R.string.key_enableSMB_after_carbs, false) && advancedFiltering)
|
||||||
this.profile.put("maxSMBBasalMinutes", sp.getInt(R.string.key_smbmaxminutes, SMBDefaults.maxSMBBasalMinutes))
|
this.profile.put("maxSMBBasalMinutes", sp.getInt(R.string.key_smbmaxminutes, SMBDefaults.maxSMBBasalMinutes))
|
||||||
this.profile.put("maxUAMSMBBasalMinutes", sp.getInt(R.string.key_uamsmbmaxminutes, SMBDefaults.maxUAMSMBBasalMinutes))
|
this.profile.put("maxUAMSMBBasalMinutes", sp.getInt(R.string.key_uamsmbmaxminutes, SMBDefaults.maxUAMSMBBasalMinutes))
|
||||||
|
this.profile.put("DynISFAdjust", SafeParse.stringToDouble(sp.getString(R.string.key_DynISFAdjust,"100")))
|
||||||
|
this.profile.put("maxUAMSMBBasalMinutes", sp.getInt(R.string.key_uamsmbmaxminutes, SMBDefaults.maxUAMSMBBasalMinutes))
|
||||||
//set the min SMB amount to be the amount set by the pump.
|
//set the min SMB amount to be the amount set by the pump.
|
||||||
this.profile.put("bolus_increment", pumpBolusStep)
|
this.profile.put("bolus_increment", pumpBolusStep)
|
||||||
this.profile.put("carbsReqThreshold", sp.getInt(R.string.key_carbsReqThreshold, SMBDefaults.carbsReqThreshold))
|
this.profile.put("carbsReqThreshold", sp.getInt(R.string.key_carbsReqThreshold, SMBDefaults.carbsReqThreshold))
|
||||||
this.profile.put("current_basal", basalRate)
|
this.profile.put("current_basal", basalRate)
|
||||||
this.profile.put("temptargetSet", tempTargetSet)
|
this.profile.put("temptargetSet", tempTargetSet)
|
||||||
this.profile.put("autosens_max", SafeParse.stringToDouble(sp.getString(R.string.key_openapsama_autosens_max, "1.2")))
|
this.profile.put("autosens_max", SafeParse.stringToDouble(sp.getString(R.string.key_openapsama_autosens_max, "1.2")))
|
||||||
|
this.profile.put("autosens_min", SafeParse.stringToDouble(sp.getString(R.string.key_openapsama_autosens_min, "0.8")))
|
||||||
|
this.profile.put("openapsama_useautosens", sp.getBoolean(R.string.key_openapsama_useautosens, false))
|
||||||
|
//set the min SMB amount to be the amount set by the pump.
|
||||||
if (profileFunction.getUnits() == GlucoseUnit.MMOL) {
|
if (profileFunction.getUnits() == GlucoseUnit.MMOL) {
|
||||||
this.profile.put("out_units", "mmol/L")
|
this.profile.put("out_units", "mmol/L")
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ class OpenAPSSMBDynamicISFPlugin @Inject constructor(
|
||||||
.pluginName(R.string.openaps_smb_dynamic_isf)
|
.pluginName(R.string.openaps_smb_dynamic_isf)
|
||||||
.description(R.string.description_smb_dynamic_isf)
|
.description(R.string.description_smb_dynamic_isf)
|
||||||
.shortName(R.string.dynisf_shortname)
|
.shortName(R.string.dynisf_shortname)
|
||||||
|
.preferencesId(R.xml.pref_openapssmbdynamicisf)
|
||||||
.setDefault(false)
|
.setDefault(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,23 +10,26 @@ import android.widget.*
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
import info.nightscout.androidaps.interfaces.Config
|
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.activities.PreferencesActivity
|
import info.nightscout.androidaps.activities.PreferencesActivity
|
||||||
|
import info.nightscout.androidaps.activities.SingleFragmentActivity
|
||||||
import info.nightscout.androidaps.databinding.ConfigbuilderFragmentBinding
|
import info.nightscout.androidaps.databinding.ConfigbuilderFragmentBinding
|
||||||
import info.nightscout.androidaps.events.EventRebuildTabs
|
import info.nightscout.androidaps.events.EventRebuildTabs
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
|
import info.nightscout.androidaps.interfaces.Config
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginBase
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginType
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.configBuilder.events.EventConfigBuilderUpdateGui
|
import info.nightscout.androidaps.plugins.configBuilder.events.EventConfigBuilderUpdateGui
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
|
||||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.PREFERENCES
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import java.util.*
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ConfigBuilderFragment : DaggerFragment() {
|
class ConfigBuilderFragment : DaggerFragment() {
|
||||||
|
@ -44,48 +47,36 @@ class ConfigBuilderFragment : DaggerFragment() {
|
||||||
|
|
||||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||||
private val pluginViewHolders = ArrayList<PluginViewHolder>()
|
private val pluginViewHolders = ArrayList<PluginViewHolder>()
|
||||||
|
private var inMenu = false
|
||||||
|
private var queryingProtection = false
|
||||||
private var _binding: ConfigbuilderFragmentBinding? = null
|
private var _binding: ConfigbuilderFragmentBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
savedInstanceState: Bundle?): View {
|
|
||||||
_binding = ConfigbuilderFragmentBinding.inflate(inflater, container, false)
|
_binding = ConfigbuilderFragmentBinding.inflate(inflater, container, false)
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
val parentClass = this.activity?.let { it::class.java }
|
||||||
if (protectionCheck.isLocked(ProtectionCheck.Protection.PREFERENCES))
|
inMenu = parentClass == SingleFragmentActivity::class.java
|
||||||
binding.mainLayout.visibility = View.GONE
|
updateProtectedUi()
|
||||||
else
|
binding.unlock.setOnClickListener { queryProtection() }
|
||||||
binding.unlock.visibility = View.GONE
|
|
||||||
|
|
||||||
binding.unlock.setOnClickListener {
|
|
||||||
activity?.let { activity ->
|
|
||||||
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, {
|
|
||||||
activity.runOnUiThread {
|
|
||||||
binding.mainLayout.visibility = View.VISIBLE
|
|
||||||
binding.unlock.visibility = View.GONE
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
if (inMenu) queryProtection() else updateProtectedUi()
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventConfigBuilderUpdateGui::class.java)
|
.toObservable(EventConfigBuilderUpdateGui::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
for (pluginViewHolder in pluginViewHolders) pluginViewHolder.update()
|
for (pluginViewHolder in pluginViewHolders) pluginViewHolder.update()
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
updateGUI()
|
updateGUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,4 +206,21 @@ class ConfigBuilderFragment : DaggerFragment() {
|
||||||
return type == PluginType.GENERAL || type == PluginType.CONSTRAINTS || type == PluginType.LOOP
|
return type == PluginType.GENERAL || type == PluginType.CONSTRAINTS || type == PluginType.LOOP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateProtectedUi() {
|
||||||
|
val isLocked = protectionCheck.isLocked(PREFERENCES)
|
||||||
|
binding.mainLayout.visibility = isLocked.not().toVisibility()
|
||||||
|
binding.unlock.visibility = isLocked.toVisibility()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun queryProtection() {
|
||||||
|
val isLocked = protectionCheck.isLocked(PREFERENCES)
|
||||||
|
if (isLocked && !queryingProtection) {
|
||||||
|
activity?.let { activity ->
|
||||||
|
queryingProtection = true
|
||||||
|
val doUpdate = { activity.runOnUiThread { queryingProtection = false; updateProtectedUi() } }
|
||||||
|
protectionCheck.queryProtection(activity, PREFERENCES, doUpdate, doUpdate, doUpdate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,6 +169,9 @@ class PluginStore @Inject constructor(
|
||||||
override val activeSafety: Safety
|
override val activeSafety: Safety
|
||||||
get() = getSpecificPluginsListByInterface(Safety::class.java).first() as Safety
|
get() = getSpecificPluginsListByInterface(Safety::class.java).first() as Safety
|
||||||
|
|
||||||
|
override val activeIobCobCalculator: IobCobCalculator
|
||||||
|
get() = getSpecificPluginsListByInterface(IobCobCalculator::class.java).first() as IobCobCalculator
|
||||||
|
|
||||||
override fun getPluginsList(): ArrayList<PluginBase> = ArrayList(plugins)
|
override fun getPluginsList(): ArrayList<PluginBase> = ArrayList(plugins)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,7 +233,7 @@ class ObjectivesFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
holder.binding.accomplished.text = rh.gs(R.string.accomplished, dateUtil.dateAndTimeString(objective.accomplishedOn))
|
holder.binding.accomplished.text = rh.gs(R.string.accomplished, dateUtil.dateAndTimeString(objective.accomplishedOn))
|
||||||
holder.binding.accomplished.setTextColor(-0x3e3e3f)
|
holder.binding.accomplished.setTextColor(rh.gac(context,R.attr.defaultTextColor))
|
||||||
holder.binding.verify.setOnClickListener {
|
holder.binding.verify.setOnClickListener {
|
||||||
receiverStatusStore.updateNetworkStatus()
|
receiverStatusStore.updateNetworkStatus()
|
||||||
if (binding.fake.isChecked) {
|
if (binding.fake.isChecked) {
|
||||||
|
|
|
@ -109,29 +109,29 @@ class SafetyPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applyBasalConstraints(absoluteRate: Constraint<Double>, profile: Profile): Constraint<Double> {
|
override fun applyBasalConstraints(absoluteRate: Constraint<Double>, profile: Profile): Constraint<Double> {
|
||||||
absoluteRate.setIfGreater(aapsLogger, 0.0, String.format(rh.gs(R.string.limitingbasalratio), 0.0, rh.gs(R.string.itmustbepositivevalue)), this)
|
absoluteRate.setIfGreater(aapsLogger, 0.0, rh.gs(R.string.limitingbasalratio, 0.0, rh.gs(R.string.itmustbepositivevalue)), this)
|
||||||
if (config.APS) {
|
if (config.APS) {
|
||||||
var maxBasal = sp.getDouble(R.string.key_openapsma_max_basal, 1.0)
|
var maxBasal = sp.getDouble(R.string.key_openapsma_max_basal, 1.0)
|
||||||
if (maxBasal < profile.getMaxDailyBasal()) {
|
if (maxBasal < profile.getMaxDailyBasal()) {
|
||||||
maxBasal = profile.getMaxDailyBasal()
|
maxBasal = profile.getMaxDailyBasal()
|
||||||
absoluteRate.addReason(rh.gs(R.string.increasingmaxbasal), this)
|
absoluteRate.addReason(rh.gs(R.string.increasingmaxbasal), this)
|
||||||
}
|
}
|
||||||
absoluteRate.setIfSmaller(aapsLogger, maxBasal, String.format(rh.gs(R.string.limitingbasalratio), maxBasal, rh.gs(R.string.maxvalueinpreferences)), this)
|
absoluteRate.setIfSmaller(aapsLogger, maxBasal,rh.gs(R.string.limitingbasalratio, maxBasal, rh.gs(R.string.maxvalueinpreferences)), this)
|
||||||
|
|
||||||
// Check percentRate but absolute rate too, because we know real current basal in pump
|
// Check percentRate but absolute rate too, because we know real current basal in pump
|
||||||
val maxBasalMultiplier = sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0)
|
val maxBasalMultiplier = sp.getDouble(R.string.key_openapsama_current_basal_safety_multiplier, 4.0)
|
||||||
val maxFromBasalMultiplier = floor(maxBasalMultiplier * profile.getBasal() * 100) / 100
|
val maxFromBasalMultiplier = floor(maxBasalMultiplier * profile.getBasal() * 100) / 100
|
||||||
absoluteRate.setIfSmaller(aapsLogger, maxFromBasalMultiplier, String.format(rh.gs(R.string.limitingbasalratio), maxFromBasalMultiplier, rh.gs(R.string.maxbasalmultiplier)), this)
|
absoluteRate.setIfSmaller(aapsLogger, maxFromBasalMultiplier, rh.gs(R.string.limitingbasalratio, maxFromBasalMultiplier, rh.gs(R.string.maxbasalmultiplier)), this)
|
||||||
val maxBasalFromDaily = sp.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3.0)
|
val maxBasalFromDaily = sp.getDouble(R.string.key_openapsama_max_daily_safety_multiplier, 3.0)
|
||||||
val maxFromDaily = floor(profile.getMaxDailyBasal() * maxBasalFromDaily * 100) / 100
|
val maxFromDaily = floor(profile.getMaxDailyBasal() * maxBasalFromDaily * 100) / 100
|
||||||
absoluteRate.setIfSmaller(aapsLogger, maxFromDaily, String.format(rh.gs(R.string.limitingbasalratio), maxFromDaily, rh.gs(R.string.maxdailybasalmultiplier)), this)
|
absoluteRate.setIfSmaller(aapsLogger, maxFromDaily,rh.gs(R.string.limitingbasalratio, maxFromDaily, rh.gs(R.string.maxdailybasalmultiplier)), this)
|
||||||
}
|
}
|
||||||
absoluteRate.setIfSmaller(aapsLogger, hardLimits.maxBasal(), String.format(rh.gs(R.string.limitingbasalratio), hardLimits.maxBasal(), rh.gs(R.string.hardlimit)), this)
|
absoluteRate.setIfSmaller(aapsLogger, hardLimits.maxBasal(),rh.gs(R.string.limitingbasalratio, hardLimits.maxBasal(), rh.gs(R.string.hardlimit)), this)
|
||||||
val pump = activePlugin.activePump
|
val pump = activePlugin.activePump
|
||||||
// check for pump max
|
// check for pump max
|
||||||
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
|
if (pump.pumpDescription.tempBasalStyle == PumpDescription.ABSOLUTE) {
|
||||||
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0
|
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0
|
||||||
absoluteRate.setIfSmaller(aapsLogger, pumpLimit, String.format(rh.gs(R.string.limitingbasalratio), pumpLimit, rh.gs(R.string.pumplimit)), this)
|
absoluteRate.setIfSmaller(aapsLogger, pumpLimit, rh.gs(R.string.limitingbasalratio, pumpLimit, rh.gs(R.string.pumplimit)), this)
|
||||||
}
|
}
|
||||||
|
|
||||||
// do rounding
|
// do rounding
|
||||||
|
@ -151,19 +151,19 @@ class SafetyPlugin @Inject constructor(
|
||||||
val pump = activePlugin.activePump
|
val pump = activePlugin.activePump
|
||||||
var percentRateAfterConst = java.lang.Double.valueOf(absoluteConstraint.value() / currentBasal * 100).toInt()
|
var percentRateAfterConst = java.lang.Double.valueOf(absoluteConstraint.value() / currentBasal * 100).toInt()
|
||||||
percentRateAfterConst = if (percentRateAfterConst < 100) Round.ceilTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt() else Round.floorTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt()
|
percentRateAfterConst = if (percentRateAfterConst < 100) Round.ceilTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt() else Round.floorTo(percentRateAfterConst.toDouble(), pump.pumpDescription.tempPercentStep.toDouble()).toInt()
|
||||||
percentRate.set(aapsLogger, percentRateAfterConst, String.format(rh.gs(R.string.limitingpercentrate), percentRateAfterConst, rh.gs(R.string.pumplimit)), this)
|
percentRate.set(aapsLogger, percentRateAfterConst, rh.gs(R.string.limitingpercentrate, percentRateAfterConst, rh.gs(R.string.pumplimit)), this)
|
||||||
if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT) {
|
if (pump.pumpDescription.tempBasalStyle == PumpDescription.PERCENT) {
|
||||||
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0
|
val pumpLimit = pump.pumpDescription.pumpType.tbrSettings?.maxDose ?: 0.0
|
||||||
percentRate.setIfSmaller(aapsLogger, pumpLimit.toInt(), String.format(rh.gs(R.string.limitingbasalratio), pumpLimit, rh.gs(R.string.pumplimit)), this)
|
percentRate.setIfSmaller(aapsLogger, pumpLimit.toInt(), rh.gs(R.string.limitingbasalratio, pumpLimit, rh.gs(R.string.pumplimit)), this)
|
||||||
}
|
}
|
||||||
return percentRate
|
return percentRate
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applyBolusConstraints(insulin: Constraint<Double>): Constraint<Double> {
|
override fun applyBolusConstraints(insulin: Constraint<Double>): Constraint<Double> {
|
||||||
insulin.setIfGreater(aapsLogger, 0.0, String.format(rh.gs(R.string.limitingbolus), 0.0, rh.gs(R.string.itmustbepositivevalue)), this)
|
insulin.setIfGreater(aapsLogger, 0.0, rh.gs(R.string.limitingbolus, 0.0, rh.gs(R.string.itmustbepositivevalue)), this)
|
||||||
val maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0)
|
val maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0)
|
||||||
insulin.setIfSmaller(aapsLogger, maxBolus, String.format(rh.gs(R.string.limitingbolus), maxBolus, rh.gs(R.string.maxvalueinpreferences)), this)
|
insulin.setIfSmaller(aapsLogger, maxBolus, rh.gs(R.string.limitingbolus, maxBolus, rh.gs(R.string.maxvalueinpreferences)), this)
|
||||||
insulin.setIfSmaller(aapsLogger, hardLimits.maxBolus(), String.format(rh.gs(R.string.limitingbolus), hardLimits.maxBolus(), rh.gs(R.string.hardlimit)), this)
|
insulin.setIfSmaller(aapsLogger, hardLimits.maxBolus(), rh.gs(R.string.limitingbolus, hardLimits.maxBolus(), rh.gs(R.string.hardlimit)), this)
|
||||||
val pump = activePlugin.activePump
|
val pump = activePlugin.activePump
|
||||||
val rounded = pump.pumpDescription.pumpType.determineCorrectBolusSize(insulin.value())
|
val rounded = pump.pumpDescription.pumpType.determineCorrectBolusSize(insulin.value())
|
||||||
insulin.setIfDifferent(aapsLogger, rounded, rh.gs(R.string.pumplimit), this)
|
insulin.setIfDifferent(aapsLogger, rounded, rh.gs(R.string.pumplimit), this)
|
||||||
|
@ -171,10 +171,10 @@ class SafetyPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applyExtendedBolusConstraints(insulin: Constraint<Double>): Constraint<Double> {
|
override fun applyExtendedBolusConstraints(insulin: Constraint<Double>): Constraint<Double> {
|
||||||
insulin.setIfGreater(aapsLogger, 0.0, String.format(rh.gs(R.string.limitingextendedbolus), 0.0, rh.gs(R.string.itmustbepositivevalue)), this)
|
insulin.setIfGreater(aapsLogger, 0.0, rh.gs(R.string.limitingextendedbolus, 0.0, rh.gs(R.string.itmustbepositivevalue)), this)
|
||||||
val maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0)
|
val maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0)
|
||||||
insulin.setIfSmaller(aapsLogger, maxBolus, String.format(rh.gs(R.string.limitingextendedbolus), maxBolus, rh.gs(R.string.maxvalueinpreferences)), this)
|
insulin.setIfSmaller(aapsLogger, maxBolus, rh.gs(R.string.limitingextendedbolus, maxBolus, rh.gs(R.string.maxvalueinpreferences)), this)
|
||||||
insulin.setIfSmaller(aapsLogger, hardLimits.maxBolus(), String.format(rh.gs(R.string.limitingextendedbolus), hardLimits.maxBolus(), rh.gs(R.string.hardlimit)), this)
|
insulin.setIfSmaller(aapsLogger, hardLimits.maxBolus(), rh.gs(R.string.limitingextendedbolus, hardLimits.maxBolus(), rh.gs(R.string.hardlimit)), this)
|
||||||
val pump = activePlugin.activePump
|
val pump = activePlugin.activePump
|
||||||
val rounded = pump.pumpDescription.pumpType.determineCorrectExtendedBolusSize(insulin.value())
|
val rounded = pump.pumpDescription.pumpType.determineCorrectExtendedBolusSize(insulin.value())
|
||||||
insulin.setIfDifferent(aapsLogger, rounded, rh.gs(R.string.pumplimit), this)
|
insulin.setIfDifferent(aapsLogger, rounded, rh.gs(R.string.pumplimit), this)
|
||||||
|
@ -182,9 +182,9 @@ class SafetyPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun applyCarbsConstraints(carbs: Constraint<Int>): Constraint<Int> {
|
override fun applyCarbsConstraints(carbs: Constraint<Int>): Constraint<Int> {
|
||||||
carbs.setIfGreater(aapsLogger, 0, String.format(rh.gs(R.string.limitingcarbs), 0, rh.gs(R.string.itmustbepositivevalue)), this)
|
carbs.setIfGreater(aapsLogger, 0, rh.gs(R.string.limitingcarbs, 0, rh.gs(R.string.itmustbepositivevalue)), this)
|
||||||
val maxCarbs = sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48)
|
val maxCarbs = sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48)
|
||||||
carbs.setIfSmaller(aapsLogger, maxCarbs, String.format(rh.gs(R.string.limitingcarbs), maxCarbs, rh.gs(R.string.maxvalueinpreferences)), this)
|
carbs.setIfSmaller(aapsLogger, maxCarbs, rh.gs(R.string.limitingcarbs, maxCarbs, rh.gs(R.string.maxvalueinpreferences)), this)
|
||||||
return carbs
|
return carbs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,11 +192,11 @@ class SafetyPlugin @Inject constructor(
|
||||||
val apsMode = sp.getString(R.string.key_aps_mode, "open")
|
val apsMode = sp.getString(R.string.key_aps_mode, "open")
|
||||||
val maxIobPref: Double = if (openAPSSMBPlugin.isEnabled() || OpenAPSSMBDynamicISFPlugin.isEnabled()) sp.getDouble(R.string.key_openapssmb_max_iob, 3.0) else sp.getDouble(R.string
|
val maxIobPref: Double = if (openAPSSMBPlugin.isEnabled() || OpenAPSSMBDynamicISFPlugin.isEnabled()) sp.getDouble(R.string.key_openapssmb_max_iob, 3.0) else sp.getDouble(R.string
|
||||||
.key_openapsma_max_iob, 1.5)
|
.key_openapsma_max_iob, 1.5)
|
||||||
maxIob.setIfSmaller(aapsLogger, maxIobPref, String.format(rh.gs(R.string.limitingiob), maxIobPref, rh.gs(R.string.maxvalueinpreferences)), this)
|
maxIob.setIfSmaller(aapsLogger, maxIobPref, rh.gs(R.string.limitingiob, maxIobPref, rh.gs(R.string.maxvalueinpreferences)), this)
|
||||||
if (openAPSAMAPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobAMA(), String.format(rh.gs(R.string.limitingiob), hardLimits.maxIobAMA(), rh.gs(R.string.hardlimit)), this)
|
if (openAPSAMAPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobAMA(), rh.gs(R.string.limitingiob, hardLimits.maxIobAMA(), rh.gs(R.string.hardlimit)), this)
|
||||||
if (openAPSSMBPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), String.format(rh.gs(R.string.limitingiob), hardLimits.maxIobSMB(), rh.gs(R.string.hardlimit)), this)
|
if (openAPSSMBPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), rh.gs(R.string.limitingiob, hardLimits.maxIobSMB(), rh.gs(R.string.hardlimit)), this)
|
||||||
if (OpenAPSSMBDynamicISFPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), String.format(rh.gs(R.string.limitingiob), hardLimits.maxIobSMB(), rh.gs(R.string.hardlimit)), this)
|
if (OpenAPSSMBDynamicISFPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), rh.gs(R.string.limitingiob, hardLimits.maxIobSMB(), rh.gs(R.string.hardlimit)), this)
|
||||||
if (apsMode == "lgs") maxIob.setIfSmaller(aapsLogger, HardLimits.MAX_IOB_LGS, String.format(rh.gs(R.string.limitingiob), HardLimits.MAX_IOB_LGS, rh.gs(R.string.lowglucosesuspend)), this)
|
if (apsMode == "lgs") maxIob.setIfSmaller(aapsLogger, HardLimits.MAX_IOB_LGS, rh.gs(R.string.limitingiob, HardLimits.MAX_IOB_LGS, rh.gs(R.string.lowglucosesuspend)), this)
|
||||||
return maxIob
|
return maxIob
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,8 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
import info.nightscout.androidaps.Constants
|
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
import info.nightscout.androidaps.activities.ErrorHelperActivity
|
||||||
import info.nightscout.androidaps.activities.HistoryBrowseActivity
|
import info.nightscout.androidaps.activities.HistoryBrowseActivity
|
||||||
|
@ -20,7 +18,7 @@ import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.database.ValueWrapper
|
import info.nightscout.androidaps.database.ValueWrapper
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
||||||
import info.nightscout.androidaps.diaconn.DiaconnG8Plugin
|
import info.nightscout.androidaps.databinding.ActionsFragmentBinding
|
||||||
import info.nightscout.androidaps.dialogs.*
|
import info.nightscout.androidaps.dialogs.*
|
||||||
import info.nightscout.androidaps.events.EventCustomActionsChanged
|
import info.nightscout.androidaps.events.EventCustomActionsChanged
|
||||||
import info.nightscout.androidaps.events.EventExtendedBolusChange
|
import info.nightscout.androidaps.events.EventExtendedBolusChange
|
||||||
|
@ -36,7 +34,6 @@ import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction
|
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.plugins.pump.omnipod.eros.OmnipodErosPumpPlugin
|
|
||||||
import info.nightscout.androidaps.queue.Callback
|
import info.nightscout.androidaps.queue.Callback
|
||||||
import info.nightscout.androidaps.skins.SkinProvider
|
import info.nightscout.androidaps.skins.SkinProvider
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
|
@ -81,88 +78,47 @@ class ActionsFragment : DaggerFragment() {
|
||||||
|
|
||||||
private val pumpCustomActions = HashMap<String, CustomAction>()
|
private val pumpCustomActions = HashMap<String, CustomAction>()
|
||||||
private val pumpCustomButtons = ArrayList<SingleClickButton>()
|
private val pumpCustomButtons = ArrayList<SingleClickButton>()
|
||||||
private var smallWidth = false
|
|
||||||
private var smallHeight = false
|
|
||||||
private lateinit var dm: DisplayMetrics
|
private lateinit var dm: DisplayMetrics
|
||||||
|
|
||||||
private var buttonsLayout: LinearLayout? = null
|
private var _binding: ActionsFragmentBinding? = null
|
||||||
private var profileSwitch: SingleClickButton? = null
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
private var tempTarget: SingleClickButton? = null
|
private val binding get() = _binding!!
|
||||||
private var extendedBolus: SingleClickButton? = null
|
|
||||||
private var extendedBolusCancel: SingleClickButton? = null
|
|
||||||
private var setTempBasal: SingleClickButton? = null
|
|
||||||
private var cancelTempBasal: SingleClickButton? = null
|
|
||||||
private var fill: SingleClickButton? = null
|
|
||||||
private var historyBrowser: SingleClickButton? = null
|
|
||||||
private var tddStats: SingleClickButton? = null
|
|
||||||
private var pumpBatteryChange: SingleClickButton? = null
|
|
||||||
|
|
||||||
private var cannulaAge: TextView? = null
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
private var insulinAge: TextView? = null
|
|
||||||
private var reservoirLevel: TextView? = null
|
|
||||||
private var sensorAge: TextView? = null
|
|
||||||
private var sensorLevel: TextView? = null
|
|
||||||
private var pbAge: TextView? = null
|
|
||||||
private var batteryLevel: TextView? = null
|
|
||||||
private var sensorLevelLabel: TextView? = null
|
|
||||||
private var insulinLevelLabel: TextView? = null
|
|
||||||
private var pbLevelLabel: TextView? = null
|
|
||||||
private var cannulaOrPatch: TextView? = null
|
|
||||||
|
|
||||||
override fun onCreateView(
|
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View? {
|
|
||||||
//check screen width
|
//check screen width
|
||||||
dm = DisplayMetrics()
|
dm = DisplayMetrics()
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R)
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
activity?.display?.getRealMetrics(dm)
|
activity?.display?.getRealMetrics(dm)
|
||||||
else
|
} else {
|
||||||
@Suppress("DEPRECATION") activity?.windowManager?.defaultDisplay?.getMetrics(dm)
|
@Suppress("DEPRECATION") activity?.windowManager?.defaultDisplay?.getMetrics(dm)
|
||||||
|
}
|
||||||
val screenWidth = dm.widthPixels
|
_binding = ActionsFragmentBinding.inflate(inflater, container, false)
|
||||||
val screenHeight = dm.heightPixels
|
return binding.root
|
||||||
smallWidth = screenWidth <= Constants.SMALL_WIDTH
|
|
||||||
smallHeight = screenHeight <= Constants.SMALL_HEIGHT
|
|
||||||
val landscape = screenHeight < screenWidth
|
|
||||||
|
|
||||||
return inflater.inflate(skinProvider.activeSkin().actionsLayout(landscape, smallWidth), container, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
buttonsLayout = view.findViewById(R.id.action_buttons_layout)
|
skinProvider.activeSkin().preProcessLandscapeActionsLayout(dm, binding)
|
||||||
profileSwitch = view.findViewById(R.id.actions_profileswitch)
|
|
||||||
tempTarget = view.findViewById(R.id.actions_temptarget)
|
|
||||||
extendedBolus = view.findViewById(R.id.actions_extendedbolus)
|
|
||||||
extendedBolusCancel = view.findViewById(R.id.actions_extendedbolus_cancel)
|
|
||||||
setTempBasal = view.findViewById(R.id.actions_settempbasal)
|
|
||||||
cancelTempBasal = view.findViewById(R.id.actions_canceltempbasal)
|
|
||||||
fill = view.findViewById(R.id.actions_fill)
|
|
||||||
historyBrowser = view.findViewById(R.id.actions_historybrowser)
|
|
||||||
tddStats = view.findViewById(R.id.actions_tddstats)
|
|
||||||
pumpBatteryChange = view.findViewById(R.id.actions_pumpbatterychange)
|
|
||||||
|
|
||||||
cannulaAge = view.findViewById(R.id.cannula_age)
|
binding.profileSwitch.setOnClickListener {
|
||||||
insulinAge = view.findViewById(R.id.insulin_age)
|
activity?.let { activity ->
|
||||||
reservoirLevel = view.findViewById(R.id.reservoir_level)
|
protectionCheck.queryProtection(
|
||||||
sensorAge = view.findViewById(R.id.sensor_age)
|
activity,
|
||||||
sensorLevel = view.findViewById(R.id.sensor_level)
|
ProtectionCheck.Protection.BOLUS,
|
||||||
pbAge = view.findViewById(R.id.pb_age)
|
UIRunnable { ProfileSwitchDialog().show(childFragmentManager, "ProfileSwitchDialog")})
|
||||||
batteryLevel = view.findViewById(R.id.battery_level)
|
}
|
||||||
sensorLevelLabel = view.findViewById(R.id.sensor_level_label)
|
|
||||||
insulinLevelLabel = view.findViewById(R.id.insulin_level_label)
|
|
||||||
pbLevelLabel = view.findViewById(R.id.pb_level_label)
|
|
||||||
cannulaOrPatch = view.findViewById(R.id.cannula_or_patch)
|
|
||||||
|
|
||||||
profileSwitch?.setOnClickListener {
|
|
||||||
ProfileSwitchDialog().show(childFragmentManager, "ProfileSwitchDialog")
|
|
||||||
}
|
}
|
||||||
tempTarget?.setOnClickListener {
|
binding.tempTarget.setOnClickListener {
|
||||||
TempTargetDialog().show(childFragmentManager, "Actions")
|
activity?.let { activity ->
|
||||||
|
protectionCheck.queryProtection(
|
||||||
|
activity,
|
||||||
|
ProtectionCheck.Protection.BOLUS,
|
||||||
|
UIRunnable { TempTargetDialog().show(childFragmentManager, "Actions") })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
extendedBolus?.setOnClickListener {
|
binding.extendedBolus.setOnClickListener {
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable {
|
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable {
|
||||||
OKDialog.showConfirmation(
|
OKDialog.showConfirmation(
|
||||||
|
@ -174,7 +130,7 @@ class ActionsFragment : DaggerFragment() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extendedBolusCancel?.setOnClickListener {
|
binding.extendedBolusCancel.setOnClickListener {
|
||||||
if (iobCobCalculator.getExtendedBolus(dateUtil.now()) != null) {
|
if (iobCobCalculator.getExtendedBolus(dateUtil.now()) != null) {
|
||||||
uel.log(Action.CANCEL_EXTENDED_BOLUS, Sources.Actions)
|
uel.log(Action.CANCEL_EXTENDED_BOLUS, Sources.Actions)
|
||||||
commandQueue.cancelExtended(object : Callback() {
|
commandQueue.cancelExtended(object : Callback() {
|
||||||
|
@ -186,10 +142,15 @@ class ActionsFragment : DaggerFragment() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setTempBasal?.setOnClickListener {
|
binding.setTempBasal.setOnClickListener {
|
||||||
TempBasalDialog().show(childFragmentManager, "Actions")
|
activity?.let { activity ->
|
||||||
|
protectionCheck.queryProtection(
|
||||||
|
activity,
|
||||||
|
ProtectionCheck.Protection.BOLUS,
|
||||||
|
UIRunnable { TempBasalDialog().show(childFragmentManager, "Actions") })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cancelTempBasal?.setOnClickListener {
|
binding.cancelTempBasal.setOnClickListener {
|
||||||
if (iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) != null) {
|
if (iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now()) != null) {
|
||||||
uel.log(Action.CANCEL_TEMP_BASAL, Sources.Actions)
|
uel.log(Action.CANCEL_TEMP_BASAL, Sources.Actions)
|
||||||
commandQueue.cancelTempBasal(true, object : Callback() {
|
commandQueue.cancelTempBasal(true, object : Callback() {
|
||||||
|
@ -201,32 +162,32 @@ class ActionsFragment : DaggerFragment() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fill?.setOnClickListener {
|
binding.fill.setOnClickListener {
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { FillDialog().show(childFragmentManager, "FillDialog") })
|
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable { FillDialog().show(childFragmentManager, "FillDialog") })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
historyBrowser?.setOnClickListener { startActivity(Intent(context, HistoryBrowseActivity::class.java)) }
|
binding.historyBrowser.setOnClickListener { startActivity(Intent(context, HistoryBrowseActivity::class.java)) }
|
||||||
tddStats?.setOnClickListener { startActivity(Intent(context, TDDStatsActivity::class.java)) }
|
binding.tddStats.setOnClickListener { startActivity(Intent(context, TDDStatsActivity::class.java)) }
|
||||||
view.findViewById<SingleClickButton>(R.id.actions_bgcheck).setOnClickListener {
|
binding.bgCheck.setOnClickListener {
|
||||||
CareDialog().setOptions(CareDialog.EventType.BGCHECK, R.string.careportal_bgcheck).show(childFragmentManager, "Actions")
|
CareDialog().setOptions(CareDialog.EventType.BGCHECK, R.string.careportal_bgcheck).show(childFragmentManager, "Actions")
|
||||||
}
|
}
|
||||||
view.findViewById<SingleClickButton>(R.id.actions_cgmsensorinsert).setOnClickListener {
|
binding.cgmSensorInsert.setOnClickListener {
|
||||||
CareDialog().setOptions(CareDialog.EventType.SENSOR_INSERT, R.string.careportal_cgmsensorinsert).show(childFragmentManager, "Actions")
|
CareDialog().setOptions(CareDialog.EventType.SENSOR_INSERT, R.string.careportal_cgmsensorinsert).show(childFragmentManager, "Actions")
|
||||||
}
|
}
|
||||||
pumpBatteryChange?.setOnClickListener {
|
binding.pumpBatteryChange.setOnClickListener {
|
||||||
CareDialog().setOptions(CareDialog.EventType.BATTERY_CHANGE, R.string.careportal_pumpbatterychange).show(childFragmentManager, "Actions")
|
CareDialog().setOptions(CareDialog.EventType.BATTERY_CHANGE, R.string.careportal_pumpbatterychange).show(childFragmentManager, "Actions")
|
||||||
}
|
}
|
||||||
view.findViewById<SingleClickButton>(R.id.actions_note).setOnClickListener {
|
binding.note.setOnClickListener {
|
||||||
CareDialog().setOptions(CareDialog.EventType.NOTE, R.string.careportal_note).show(childFragmentManager, "Actions")
|
CareDialog().setOptions(CareDialog.EventType.NOTE, R.string.careportal_note).show(childFragmentManager, "Actions")
|
||||||
}
|
}
|
||||||
view.findViewById<SingleClickButton>(R.id.actions_exercise).setOnClickListener {
|
binding.exercise.setOnClickListener {
|
||||||
CareDialog().setOptions(CareDialog.EventType.EXERCISE, R.string.careportal_exercise).show(childFragmentManager, "Actions")
|
CareDialog().setOptions(CareDialog.EventType.EXERCISE, R.string.careportal_exercise).show(childFragmentManager, "Actions")
|
||||||
}
|
}
|
||||||
view.findViewById<SingleClickButton>(R.id.actions_question).setOnClickListener {
|
binding.question.setOnClickListener {
|
||||||
CareDialog().setOptions(CareDialog.EventType.QUESTION, R.string.careportal_question).show(childFragmentManager, "Actions")
|
CareDialog().setOptions(CareDialog.EventType.QUESTION, R.string.careportal_question).show(childFragmentManager, "Actions")
|
||||||
}
|
}
|
||||||
view.findViewById<SingleClickButton>(R.id.actions_announcement).setOnClickListener {
|
binding.announcement.setOnClickListener {
|
||||||
CareDialog().setOptions(CareDialog.EventType.ANNOUNCEMENT, R.string.careportal_announcement).show(childFragmentManager, "Actions")
|
CareDialog().setOptions(CareDialog.EventType.ANNOUNCEMENT, R.string.careportal_announcement).show(childFragmentManager, "Actions")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,13 +226,18 @@ class ActionsFragment : DaggerFragment() {
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun updateGui() {
|
fun updateGui() {
|
||||||
|
|
||||||
val profile = profileFunction.getProfile()
|
val profile = profileFunction.getProfile()
|
||||||
val pump = activePlugin.activePump
|
val pump = activePlugin.activePump
|
||||||
|
|
||||||
profileSwitch?.visibility = (
|
binding.profileSwitch.visibility = (
|
||||||
activePlugin.activeProfileSource.profile != null &&
|
activePlugin.activeProfileSource.profile != null &&
|
||||||
pump.pumpDescription.isSetBasalProfileCapable &&
|
pump.pumpDescription.isSetBasalProfileCapable &&
|
||||||
pump.isInitialized() &&
|
pump.isInitialized() &&
|
||||||
|
@ -279,60 +245,58 @@ class ActionsFragment : DaggerFragment() {
|
||||||
!loop.isDisconnected).toVisibility()
|
!loop.isDisconnected).toVisibility()
|
||||||
|
|
||||||
if (!pump.pumpDescription.isExtendedBolusCapable || !pump.isInitialized() || pump.isSuspended() || loop.isDisconnected || pump.isFakingTempsByExtendedBoluses || config.NSCLIENT) {
|
if (!pump.pumpDescription.isExtendedBolusCapable || !pump.isInitialized() || pump.isSuspended() || loop.isDisconnected || pump.isFakingTempsByExtendedBoluses || config.NSCLIENT) {
|
||||||
extendedBolus?.visibility = View.GONE
|
binding.extendedBolus.visibility = View.GONE
|
||||||
extendedBolusCancel?.visibility = View.GONE
|
binding.extendedBolusCancel.visibility = View.GONE
|
||||||
} else {
|
} else {
|
||||||
val activeExtendedBolus = repository.getExtendedBolusActiveAt(dateUtil.now()).blockingGet()
|
val activeExtendedBolus = repository.getExtendedBolusActiveAt(dateUtil.now()).blockingGet()
|
||||||
if (activeExtendedBolus is ValueWrapper.Existing) {
|
if (activeExtendedBolus is ValueWrapper.Existing) {
|
||||||
extendedBolus?.visibility = View.GONE
|
binding.extendedBolus.visibility = View.GONE
|
||||||
extendedBolusCancel?.visibility = View.VISIBLE
|
binding.extendedBolusCancel.visibility = View.VISIBLE
|
||||||
@Suppress("SetTextI18n")
|
@Suppress("SetTextI18n")
|
||||||
extendedBolusCancel?.text = rh.gs(R.string.cancel) + " " + activeExtendedBolus.value.toStringMedium(dateUtil)
|
binding.extendedBolusCancel.text = rh.gs(R.string.cancel) + " " + activeExtendedBolus.value.toStringMedium(dateUtil)
|
||||||
} else {
|
} else {
|
||||||
extendedBolus?.visibility = View.VISIBLE
|
binding.extendedBolus.visibility = View.VISIBLE
|
||||||
extendedBolusCancel?.visibility = View.GONE
|
binding.extendedBolusCancel.visibility = View.GONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pump.pumpDescription.isTempBasalCapable || !pump.isInitialized() || pump.isSuspended() || loop.isDisconnected || config.NSCLIENT) {
|
if (!pump.pumpDescription.isTempBasalCapable || !pump.isInitialized() || pump.isSuspended() || loop.isDisconnected || config.NSCLIENT) {
|
||||||
setTempBasal?.visibility = View.GONE
|
binding.setTempBasal.visibility = View.GONE
|
||||||
cancelTempBasal?.visibility = View.GONE
|
binding.cancelTempBasal.visibility = View.GONE
|
||||||
} else {
|
} else {
|
||||||
val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis())
|
val activeTemp = iobCobCalculator.getTempBasalIncludingConvertedExtended(System.currentTimeMillis())
|
||||||
if (activeTemp != null) {
|
if (activeTemp != null) {
|
||||||
setTempBasal?.visibility = View.GONE
|
binding.setTempBasal.visibility = View.GONE
|
||||||
cancelTempBasal?.visibility = View.VISIBLE
|
binding.cancelTempBasal.visibility = View.VISIBLE
|
||||||
@Suppress("SetTextI18n")
|
@Suppress("SetTextI18n")
|
||||||
cancelTempBasal?.text = rh.gs(R.string.cancel) + " " + activeTemp.toStringShort()
|
binding.cancelTempBasal.text = rh.gs(R.string.cancel) + " " + activeTemp.toStringShort()
|
||||||
} else {
|
} else {
|
||||||
setTempBasal?.visibility = View.VISIBLE
|
binding.setTempBasal.visibility = View.VISIBLE
|
||||||
cancelTempBasal?.visibility = View.GONE
|
binding.cancelTempBasal.visibility = View.GONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val activeBgSource = activePlugin.activeBgSource
|
val activeBgSource = activePlugin.activeBgSource
|
||||||
historyBrowser?.visibility = (profile != null).toVisibility()
|
binding.historyBrowser.visibility = (profile != null).toVisibility()
|
||||||
fill?.visibility = (pump.pumpDescription.isRefillingCapable && pump.isInitialized() && !pump.isSuspended()).toVisibility()
|
binding.fill.visibility = (pump.pumpDescription.isRefillingCapable && pump.isInitialized() && !pump.isSuspended()).toVisibility()
|
||||||
if (pump is DiaconnG8Plugin) {
|
binding.pumpBatteryChange.visibility = (pump.pumpDescription.isBatteryReplaceable || pump.isBatteryChangeLoggingEnabled()).toVisibility()
|
||||||
pumpBatteryChange?.visibility = (pump.pumpDescription.isBatteryReplaceable && !pump.isBatteryChangeLoggingEnabled()).toVisibility()
|
binding.tempTarget.visibility = (profile != null && !loop.isDisconnected).toVisibility()
|
||||||
} else {
|
binding.tddStats.visibility = pump.pumpDescription.supportsTDDs.toVisibility()
|
||||||
pumpBatteryChange?.visibility =
|
val isPatchPump = pump.pumpDescription.isPatchPump
|
||||||
(pump.pumpDescription.isBatteryReplaceable || (pump is OmnipodErosPumpPlugin && pump.isUseRileyLinkBatteryLevel && pump.isBatteryChangeLoggingEnabled)).toVisibility()
|
binding.status.apply {
|
||||||
}
|
cannulaOrPatch.text = if (isPatchPump) rh.gs(R.string.patch_pump) else rh.gs(R.string.cannula)
|
||||||
tempTarget?.visibility = (profile != null && !loop.isDisconnected).toVisibility()
|
val imageResource = if (isPatchPump) R.drawable.ic_patch_pump_outline else R.drawable.ic_cp_age_cannula
|
||||||
tddStats?.visibility = pump.pumpDescription.supportsTDDs.toVisibility()
|
cannulaOrPatch.setCompoundDrawablesWithIntrinsicBounds(imageResource, 0, 0, 0)
|
||||||
|
batteryLayout.visibility = (!isPatchPump || pump.pumpDescription.useHardwareLink).toVisibility()
|
||||||
|
|
||||||
cannulaOrPatch?.text = if (pump.pumpDescription.isPatchPump) rh.gs(R.string.patch_pump) else rh.gs(R.string.cannula)
|
if (!config.NSCLIENT) {
|
||||||
val imageResource = if (pump.pumpDescription.isPatchPump) R.drawable.ic_patch_pump_outline else R.drawable.ic_cp_age_cannula
|
statusLightHandler.updateStatusLights(cannulaAge, insulinAge, reservoirLevel, sensorAge, sensorLevel, pbAge, batteryLevel)
|
||||||
cannulaOrPatch?.setCompoundDrawablesWithIntrinsicBounds(imageResource, 0, 0, 0)
|
sensorLevelLabel.text = if (activeBgSource.sensorBatteryLevel == -1) "" else rh.gs(R.string.careportal_level_label)
|
||||||
|
} else {
|
||||||
if (!config.NSCLIENT) {
|
statusLightHandler.updateStatusLights(cannulaAge, insulinAge, null, sensorAge, null, pbAge, null)
|
||||||
statusLightHandler.updateStatusLights(cannulaAge, insulinAge, reservoirLevel, sensorAge, sensorLevel, pbAge, batteryLevel)
|
sensorLevelLabel.text = ""
|
||||||
sensorLevelLabel?.text = if (activeBgSource.sensorBatteryLevel == -1) "" else rh.gs(R.string.careportal_level_label)
|
insulinLevelLabel.text = ""
|
||||||
} else {
|
pbLevelLabel.text = ""
|
||||||
statusLightHandler.updateStatusLights(cannulaAge, insulinAge, null, sensorAge, null, pbAge, null)
|
}
|
||||||
sensorLevelLabel?.text = ""
|
|
||||||
insulinLevelLabel?.text = ""
|
|
||||||
pbLevelLabel?.text = ""
|
|
||||||
}
|
}
|
||||||
checkPumpCustomActions()
|
checkPumpCustomActions()
|
||||||
|
|
||||||
|
@ -365,7 +329,7 @@ class ActionsFragment : DaggerFragment() {
|
||||||
val top = activity?.let { ContextCompat.getDrawable(it, customAction.iconResourceId) }
|
val top = activity?.let { ContextCompat.getDrawable(it, customAction.iconResourceId) }
|
||||||
btn.setCompoundDrawablesWithIntrinsicBounds(null, top, null, null)
|
btn.setCompoundDrawablesWithIntrinsicBounds(null, top, null, null)
|
||||||
|
|
||||||
buttonsLayout?.addView(btn)
|
binding.buttonsLayout.addView(btn)
|
||||||
|
|
||||||
this.pumpCustomActions[rh.gs(customAction.name)] = customAction
|
this.pumpCustomActions[rh.gs(customAction.name)] = customAction
|
||||||
this.pumpCustomButtons.add(btn)
|
this.pumpCustomButtons.add(btn)
|
||||||
|
@ -373,7 +337,7 @@ class ActionsFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removePumpCustomActions() {
|
private fun removePumpCustomActions() {
|
||||||
for (customButton in pumpCustomButtons) buttonsLayout?.removeView(customButton)
|
for (customButton in pumpCustomButtons) binding.buttonsLayout.removeView(customButton)
|
||||||
pumpCustomButtons.clear()
|
pumpCustomButtons.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,12 +6,11 @@ import android.content.pm.ResolveInfo
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.events.*
|
import info.nightscout.androidaps.events.Event
|
||||||
|
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
||||||
import info.nightscout.androidaps.extensions.durationInMinutes
|
import info.nightscout.androidaps.extensions.durationInMinutes
|
||||||
import info.nightscout.androidaps.extensions.toStringFull
|
import info.nightscout.androidaps.extensions.toStringFull
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
|
import info.nightscout.androidaps.plugins.aps.events.EventOpenAPSUpdateGui
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.data.DeviceStatusData
|
import info.nightscout.androidaps.plugins.general.nsclient.data.DeviceStatusData
|
||||||
|
@ -25,6 +24,8 @@ import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
@ -68,26 +69,6 @@ class DataBroadcastPlugin @Inject constructor(
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ sendData(it) }, fabricPrivacy::logException)
|
.subscribe({ sendData(it) }, fabricPrivacy::logException)
|
||||||
)
|
)
|
||||||
disposable.add(rxBus
|
|
||||||
.toObservable(EventExtendedBolusChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ sendData(it) }, fabricPrivacy::logException)
|
|
||||||
)
|
|
||||||
disposable.add(rxBus
|
|
||||||
.toObservable(EventTempBasalChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ sendData(it) }, fabricPrivacy::logException)
|
|
||||||
)
|
|
||||||
disposable.add(rxBus
|
|
||||||
.toObservable(EventTreatmentChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ sendData(it) }, fabricPrivacy::logException)
|
|
||||||
)
|
|
||||||
disposable.add(rxBus
|
|
||||||
.toObservable(EventEffectiveProfileSwitchChanged::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ sendData(it) }, fabricPrivacy::logException)
|
|
||||||
)
|
|
||||||
disposable.add(rxBus
|
disposable.add(rxBus
|
||||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.food
|
package info.nightscout.androidaps.plugins.general.food
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.graphics.Paint
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
|
@ -24,18 +23,18 @@ import info.nightscout.androidaps.databinding.FoodFragmentBinding
|
||||||
import info.nightscout.androidaps.databinding.FoodItemBinding
|
import info.nightscout.androidaps.databinding.FoodItemBinding
|
||||||
import info.nightscout.androidaps.dialogs.WizardDialog
|
import info.nightscout.androidaps.dialogs.WizardDialog
|
||||||
import info.nightscout.androidaps.events.EventFoodDatabaseChanged
|
import info.nightscout.androidaps.events.EventFoodDatabaseChanged
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
|
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.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.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.androidaps.utils.ui.UIRunnable
|
import info.nightscout.androidaps.utils.ui.UIRunnable
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import io.reactivex.rxjava3.core.Completable
|
import io.reactivex.rxjava3.core.Completable
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
@ -43,7 +42,6 @@ import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
class FoodFragment : DaggerFragment() {
|
class FoodFragment : DaggerFragment() {
|
||||||
|
|
||||||
|
@ -66,10 +64,8 @@ class FoodFragment : DaggerFragment() {
|
||||||
// onDestroyView.
|
// onDestroyView.
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||||
_binding = FoodFragmentBinding.inflate(inflater, container, false)
|
FoodFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root
|
||||||
return binding.root
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
@ -80,8 +76,10 @@ class FoodFragment : DaggerFragment() {
|
||||||
binding.refreshFromNightscout.setOnClickListener {
|
binding.refreshFromNightscout.setOnClickListener {
|
||||||
context?.let { context ->
|
context?.let { context ->
|
||||||
OKDialog.showConfirmation(context, rh.gs(R.string.refresheventsfromnightscout) + " ?", {
|
OKDialog.showConfirmation(context, rh.gs(R.string.refresheventsfromnightscout) + " ?", {
|
||||||
uel.log(Action.FOOD, Sources.Food, rh.gs(R.string.refresheventsfromnightscout),
|
uel.log(
|
||||||
ValueWithUnit.SimpleString(rh.gsNotLocalised(R.string.refresheventsfromnightscout)))
|
Action.FOOD, Sources.Food, rh.gs(R.string.refresheventsfromnightscout),
|
||||||
|
ValueWithUnit.SimpleString(rh.gsNotLocalised(R.string.refresheventsfromnightscout))
|
||||||
|
)
|
||||||
disposable += Completable.fromAction { repository.deleteAllFoods() }
|
disposable += Completable.fromAction { repository.deleteAllFoods() }
|
||||||
.subscribeOn(aapsSchedulers.io)
|
.subscribeOn(aapsSchedulers.io)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
|
@ -95,32 +93,14 @@ class FoodFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.clearfilter.setOnClickListener {
|
binding.filterinputLayout.setEndIconOnClickListener {
|
||||||
binding.filter.setText("")
|
binding.filter.setText("")
|
||||||
binding.category.setSelection(0)
|
binding.categoryList.setText(rh.gs(R.string.none), false)
|
||||||
binding.subcategory.setSelection(0)
|
binding.subcategoryList.setText(rh.gs(R.string.none), false)
|
||||||
filterData()
|
filterData()
|
||||||
}
|
}
|
||||||
binding.category.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
binding.categoryList.onItemClickListener = AdapterView.OnItemClickListener { _, _, _, _ -> fillSubcategories(); filterData() }
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
binding.subcategoryList.onItemClickListener = AdapterView.OnItemClickListener { _, _, _, _ -> filterData() }
|
||||||
fillSubcategories()
|
|
||||||
filterData()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
|
||||||
fillSubcategories()
|
|
||||||
filterData()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.subcategory.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
|
||||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
|
||||||
filterData()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNothingSelected(parent: AdapterView<*>?) {
|
|
||||||
filterData()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
binding.filter.addTextChangedListener(object : TextWatcher {
|
binding.filter.addTextChangedListener(object : TextWatcher {
|
||||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||||
|
@ -134,12 +114,11 @@ class FoodFragment : DaggerFragment() {
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
disposable.add(rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventFoodDatabaseChanged::class.java)
|
.toObservable(EventFoodDatabaseChanged::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
.debounce(1L, TimeUnit.SECONDS)
|
||||||
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
.subscribe({ swapAdapter() }, fabricPrivacy::logException)
|
||||||
)
|
|
||||||
swapAdapter()
|
swapAdapter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,13 +157,13 @@ class FoodFragment : DaggerFragment() {
|
||||||
val categories = ArrayList(catSet)
|
val categories = ArrayList(catSet)
|
||||||
categories.add(0, rh.gs(R.string.none))
|
categories.add(0, rh.gs(R.string.none))
|
||||||
context?.let { context ->
|
context?.let { context ->
|
||||||
val adapterCategories = ArrayAdapter(context, R.layout.spinner_centered, categories)
|
binding.categoryList.setAdapter(ArrayAdapter(context, R.layout.spinner_centered, categories))
|
||||||
binding.category.adapter = adapterCategories
|
binding.categoryList.setText(rh.gs(R.string.none), false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fillSubcategories() {
|
private fun fillSubcategories() {
|
||||||
val categoryFilter = binding.category.selectedItem.toString()
|
val categoryFilter = binding.categoryList.text.toString()
|
||||||
val subCatSet: MutableSet<CharSequence> = HashSet()
|
val subCatSet: MutableSet<CharSequence> = HashSet()
|
||||||
if (categoryFilter != rh.gs(R.string.none)) {
|
if (categoryFilter != rh.gs(R.string.none)) {
|
||||||
for (f in unfiltered) {
|
for (f in unfiltered) {
|
||||||
|
@ -198,17 +177,15 @@ class FoodFragment : DaggerFragment() {
|
||||||
val subcategories = ArrayList(subCatSet)
|
val subcategories = ArrayList(subCatSet)
|
||||||
subcategories.add(0, rh.gs(R.string.none))
|
subcategories.add(0, rh.gs(R.string.none))
|
||||||
context?.let { context ->
|
context?.let { context ->
|
||||||
val adapterSubcategories = ArrayAdapter(context, R.layout.spinner_centered, subcategories)
|
binding.subcategoryList.setAdapter(ArrayAdapter(context, R.layout.spinner_centered, subcategories))
|
||||||
binding.subcategory.adapter = adapterSubcategories
|
binding.subcategoryList.setText(rh.gs(R.string.none), false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun filterData() {
|
private fun filterData() {
|
||||||
val textFilter = binding.filter.text.toString()
|
val textFilter = binding.filter.text.toString()
|
||||||
val categoryFilter = binding.category.selectedItem?.toString()
|
val categoryFilter = binding.categoryList.text.toString()
|
||||||
?: rh.gs(R.string.none)
|
val subcategoryFilter = binding.subcategoryList.text.toString()
|
||||||
val subcategoryFilter = binding.subcategory.selectedItem?.toString()
|
|
||||||
?: rh.gs(R.string.none)
|
|
||||||
val newFiltered = ArrayList<Food>()
|
val newFiltered = ArrayList<Food>()
|
||||||
for (f in unfiltered) {
|
for (f in unfiltered) {
|
||||||
if (f.category == null || f.subCategory == null) continue
|
if (f.category == null || f.subCategory == null) continue
|
||||||
|
@ -267,18 +244,17 @@ class FoodFragment : DaggerFragment() {
|
||||||
}, null)
|
}, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.icCalculator.setOnClickListener { v:View ->
|
binding.icCalculator.setOnClickListener { v: View ->
|
||||||
val food = v.tag as Food
|
val food = v.tag as Food
|
||||||
activity?.let { activity ->
|
activity?.let { activity ->
|
||||||
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable {
|
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable {
|
||||||
if (isAdded) {
|
if (isAdded)
|
||||||
val wizardDialog = WizardDialog()
|
WizardDialog().also { dialog ->
|
||||||
val bundle = Bundle()
|
dialog.arguments = Bundle().also { bundle ->
|
||||||
bundle.putInt("carbs_input", food.carbs)
|
bundle.putDouble("carbs_input", food.carbs.toDouble())
|
||||||
bundle.putString("notes_input", " ${food.name} - ${food.carbs}g")
|
bundle.putString("notes_input", " ${food.name} - ${food.carbs}g")
|
||||||
wizardDialog.setArguments(bundle)
|
}
|
||||||
wizardDialog.show(childFragmentManager, "Food Item")
|
}.show(childFragmentManager, "Food Item")
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.activities.SingleFragmentActivity
|
||||||
import info.nightscout.androidaps.dana.database.DanaHistoryDatabase
|
import info.nightscout.androidaps.dana.database.DanaHistoryDatabase
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
||||||
|
@ -14,6 +15,7 @@ import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
||||||
import info.nightscout.androidaps.databinding.MaintenanceFragmentBinding
|
import info.nightscout.androidaps.databinding.MaintenanceFragmentBinding
|
||||||
import info.nightscout.androidaps.diaconn.database.DiaconnHistoryDatabase
|
import info.nightscout.androidaps.diaconn.database.DiaconnHistoryDatabase
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||||
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.insight.database.InsightDatabase
|
import info.nightscout.androidaps.insight.database.InsightDatabase
|
||||||
import info.nightscout.androidaps.interfaces.DataSyncSelector
|
import info.nightscout.androidaps.interfaces.DataSyncSelector
|
||||||
import info.nightscout.androidaps.interfaces.ImportExportPrefs
|
import info.nightscout.androidaps.interfaces.ImportExportPrefs
|
||||||
|
@ -27,6 +29,8 @@ import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.DashHistoryDatabase
|
import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.database.DashHistoryDatabase
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.eros.history.database.ErosHistoryDatabase
|
import info.nightscout.androidaps.plugins.pump.omnipod.eros.history.database.ErosHistoryDatabase
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck
|
||||||
|
import info.nightscout.androidaps.utils.protection.ProtectionCheck.Protection.PREFERENCES
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import io.reactivex.rxjava3.core.Completable.fromAction
|
import io.reactivex.rxjava3.core.Completable.fromAction
|
||||||
|
@ -48,6 +52,7 @@ class MaintenanceFragment : DaggerFragment() {
|
||||||
@Inject lateinit var diaconnDatabase: DiaconnHistoryDatabase
|
@Inject lateinit var diaconnDatabase: DiaconnHistoryDatabase
|
||||||
@Inject lateinit var erosDatabase: ErosHistoryDatabase
|
@Inject lateinit var erosDatabase: ErosHistoryDatabase
|
||||||
@Inject lateinit var dashDatabase: DashHistoryDatabase
|
@Inject lateinit var dashDatabase: DashHistoryDatabase
|
||||||
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
@Inject lateinit var dataSyncSelector: DataSyncSelector
|
@Inject lateinit var dataSyncSelector: DataSyncSelector
|
||||||
@Inject lateinit var pumpSync: PumpSync
|
@Inject lateinit var pumpSync: PumpSync
|
||||||
|
@ -55,11 +60,11 @@ class MaintenanceFragment : DaggerFragment() {
|
||||||
@Inject lateinit var overviewData: OverviewData
|
@Inject lateinit var overviewData: OverviewData
|
||||||
|
|
||||||
private val compositeDisposable = CompositeDisposable()
|
private val compositeDisposable = CompositeDisposable()
|
||||||
|
private var inMenu = false
|
||||||
|
private var queryingProtection = false
|
||||||
private var _binding: MaintenanceFragmentBinding? = null
|
private var _binding: MaintenanceFragmentBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
|
@ -69,6 +74,9 @@ class MaintenanceFragment : DaggerFragment() {
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
val parentClass = this.activity?.let { it::class.java }
|
||||||
|
inMenu = parentClass == SingleFragmentActivity::class.java
|
||||||
|
updateProtectedUi()
|
||||||
binding.logSend.setOnClickListener { maintenancePlugin.sendLogs() }
|
binding.logSend.setOnClickListener { maintenancePlugin.sendLogs() }
|
||||||
binding.logDelete.setOnClickListener {
|
binding.logDelete.setOnClickListener {
|
||||||
uel.log(Action.DELETE_LOGS, Sources.Maintenance)
|
uel.log(Action.DELETE_LOGS, Sources.Maintenance)
|
||||||
|
@ -128,6 +136,13 @@ class MaintenanceFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.unlock.setOnClickListener { queryProtection() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
if (inMenu) queryProtection() else updateProtectedUi()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
@ -136,4 +151,21 @@ class MaintenanceFragment : DaggerFragment() {
|
||||||
compositeDisposable.clear()
|
compositeDisposable.clear()
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateProtectedUi() {
|
||||||
|
val isLocked = protectionCheck.isLocked(PREFERENCES)
|
||||||
|
binding.mainLayout.visibility = isLocked.not().toVisibility()
|
||||||
|
binding.unlock.visibility = isLocked.toVisibility()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun queryProtection() {
|
||||||
|
val isLocked = protectionCheck.isLocked(PREFERENCES)
|
||||||
|
if (isLocked && !queryingProtection) {
|
||||||
|
activity?.let { activity ->
|
||||||
|
queryingProtection = true
|
||||||
|
val doUpdate = { activity.runOnUiThread { queryingProtection = false; updateProtectedUi() } }
|
||||||
|
protectionCheck.queryProtection(activity, PREFERENCES, doUpdate, doUpdate, doUpdate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -64,8 +64,6 @@ class MaintenancePlugin @Inject constructor(
|
||||||
context.startActivity(emailIntent)
|
context.startActivity(emailIntent)
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo replace this with a call on startup of the application, specifically to remove
|
|
||||||
// unnecessary garbage from the log exports
|
|
||||||
fun deleteLogs(keep: Int) {
|
fun deleteLogs(keep: Int) {
|
||||||
val logDir = File(loggerUtils.logDirectory)
|
val logDir = File(loggerUtils.logDirectory)
|
||||||
val files = logDir.listFiles { _: File?, name: String ->
|
val files = logDir.listFiles { _: File?, name: String ->
|
||||||
|
|
|
@ -170,8 +170,7 @@ class NSClientPlugin @Inject constructor(
|
||||||
|
|
||||||
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
override fun onServiceConnected(name: ComponentName, service: IBinder) {
|
||||||
aapsLogger.debug(LTag.NSCLIENT, "Service is connected")
|
aapsLogger.debug(LTag.NSCLIENT, "Service is connected")
|
||||||
val mLocalBinder = service as NSClientService.LocalBinder
|
val mLocalBinder = service as NSClientService.LocalBinder?
|
||||||
@Suppress("UNNECESSARY_SAFE_CALL")
|
|
||||||
nsClientService = mLocalBinder?.serviceInstance // is null when running in roboelectric
|
nsClientService = mLocalBinder?.serviceInstance // is null when running in roboelectric
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,7 +190,7 @@ class NSClientService : DaggerService() {
|
||||||
lastAckTime = dateUtil.now()
|
lastAckTime = dateUtil.now()
|
||||||
dataWorker.enqueue(
|
dataWorker.enqueue(
|
||||||
OneTimeWorkRequest.Builder(NSClientAddAckWorker::class.java)
|
OneTimeWorkRequest.Builder(NSClientAddAckWorker::class.java)
|
||||||
.setInputData(dataWorker.storeInputData(ack, null))
|
.setInputData(dataWorker.storeInputData(ack))
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ class NSClientService : DaggerService() {
|
||||||
lastAckTime = dateUtil.now()
|
lastAckTime = dateUtil.now()
|
||||||
dataWorker.enqueue(
|
dataWorker.enqueue(
|
||||||
OneTimeWorkRequest.Builder(NSClientUpdateRemoveAckWorker::class.java)
|
OneTimeWorkRequest.Builder(NSClientUpdateRemoveAckWorker::class.java)
|
||||||
.setInputData(dataWorker.storeInputData(ack, null))
|
.setInputData(dataWorker.storeInputData(ack))
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -483,7 +483,7 @@ class NSClientService : DaggerService() {
|
||||||
rxBus.send(EventNSClientNewLog("PROFILE", "profile received"))
|
rxBus.send(EventNSClientNewLog("PROFILE", "profile received"))
|
||||||
dataWorker.enqueue(
|
dataWorker.enqueue(
|
||||||
OneTimeWorkRequest.Builder(LocalProfilePlugin.NSProfileWorker::class.java)
|
OneTimeWorkRequest.Builder(LocalProfilePlugin.NSProfileWorker::class.java)
|
||||||
.setInputData(dataWorker.storeInputData(profileStoreJson, null))
|
.setInputData(dataWorker.storeInputData(profileStoreJson))
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
xDripBroadcast.sendProfile(profileStoreJson)
|
xDripBroadcast.sendProfile(profileStoreJson)
|
||||||
|
@ -502,7 +502,7 @@ class NSClientService : DaggerService() {
|
||||||
if (addedOrUpdatedTreatments.length() > 0) {
|
if (addedOrUpdatedTreatments.length() > 0) {
|
||||||
dataWorker.enqueue(
|
dataWorker.enqueue(
|
||||||
OneTimeWorkRequest.Builder(NSClientAddUpdateWorker::class.java)
|
OneTimeWorkRequest.Builder(NSClientAddUpdateWorker::class.java)
|
||||||
.setInputData(dataWorker.storeInputData(addedOrUpdatedTreatments, null))
|
.setInputData(dataWorker.storeInputData(addedOrUpdatedTreatments))
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
xDripBroadcast.sendTreatments(addedOrUpdatedTreatments)
|
xDripBroadcast.sendTreatments(addedOrUpdatedTreatments)
|
||||||
|
@ -520,7 +520,7 @@ class NSClientService : DaggerService() {
|
||||||
if (foods.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + foods.length() + " foods"))
|
if (foods.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + foods.length() + " foods"))
|
||||||
dataWorker.enqueue(
|
dataWorker.enqueue(
|
||||||
OneTimeWorkRequest.Builder(FoodWorker::class.java)
|
OneTimeWorkRequest.Builder(FoodWorker::class.java)
|
||||||
.setInputData(dataWorker.storeInputData(foods, null))
|
.setInputData(dataWorker.storeInputData(foods))
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -529,7 +529,7 @@ class NSClientService : DaggerService() {
|
||||||
if (mbgArray.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + mbgArray.length() + " mbgs"))
|
if (mbgArray.length() > 0) rxBus.send(EventNSClientNewLog("DATA", "received " + mbgArray.length() + " mbgs"))
|
||||||
dataWorker.enqueue(
|
dataWorker.enqueue(
|
||||||
OneTimeWorkRequest.Builder(NSClientMbgWorker::class.java)
|
OneTimeWorkRequest.Builder(NSClientMbgWorker::class.java)
|
||||||
.setInputData(dataWorker.storeInputData(mbgArray, null))
|
.setInputData(dataWorker.storeInputData(mbgArray))
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -546,7 +546,7 @@ class NSClientService : DaggerService() {
|
||||||
sp.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, true)
|
sp.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, true)
|
||||||
dataWorker.enqueue(
|
dataWorker.enqueue(
|
||||||
OneTimeWorkRequest.Builder(NSClientSourceWorker::class.java)
|
OneTimeWorkRequest.Builder(NSClientSourceWorker::class.java)
|
||||||
.setInputData(dataWorker.storeInputData(sgvs, null))
|
.setInputData(dataWorker.storeInputData(sgvs))
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
xDripBroadcast.sendSgvs(sgvs)
|
xDripBroadcast.sendSgvs(sgvs)
|
||||||
|
|
|
@ -1,44 +1,42 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview
|
package info.nightscout.androidaps.plugins.general.overview
|
||||||
|
|
||||||
import android.graphics.DashPathEffect
|
import android.content.Context
|
||||||
import android.graphics.Paint
|
import androidx.annotation.ColorInt
|
||||||
import com.jjoe64.graphview.series.BarGraphSeries
|
import com.jjoe64.graphview.series.BarGraphSeries
|
||||||
import com.jjoe64.graphview.series.DataPoint
|
import com.jjoe64.graphview.series.DataPoint
|
||||||
import com.jjoe64.graphview.series.LineGraphSeries
|
import com.jjoe64.graphview.series.LineGraphSeries
|
||||||
import dagger.android.HasAndroidInjector
|
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.data.IobTotal
|
import info.nightscout.androidaps.data.IobTotal
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.database.ValueWrapper
|
import info.nightscout.androidaps.database.ValueWrapper
|
||||||
import info.nightscout.androidaps.database.entities.Bolus
|
|
||||||
import info.nightscout.androidaps.database.entities.GlucoseValue
|
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||||
import info.nightscout.androidaps.database.entities.TemporaryTarget
|
import info.nightscout.androidaps.database.entities.TemporaryTarget
|
||||||
import info.nightscout.androidaps.database.entities.TherapyEvent
|
import info.nightscout.androidaps.extensions.convertedToPercent
|
||||||
import info.nightscout.androidaps.extensions.*
|
import info.nightscout.androidaps.extensions.isInProgress
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.extensions.toStringFull
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.androidaps.extensions.toStringShort
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.androidaps.extensions.valueToUnits
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus
|
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.*
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensResult
|
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.DataPointWithLabelInterface
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.FixedLineGraphSeries
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.PointsWithLabelGraphSeries
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.Scale
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.ScaledDataPoint
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.*
|
import info.nightscout.androidaps.utils.DefaultValueHelper
|
||||||
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
import kotlin.math.abs
|
|
||||||
import kotlin.math.ceil
|
|
||||||
import kotlin.math.max
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
class OverviewData @Inject constructor(
|
class OverviewData @Inject constructor(
|
||||||
private val injector: HasAndroidInjector,
|
|
||||||
private val aapsLogger: AAPSLogger,
|
private val aapsLogger: AAPSLogger,
|
||||||
private val rh: ResourceHelper,
|
private val rh: ResourceHelper,
|
||||||
private val dateUtil: DateUtil,
|
private val dateUtil: DateUtil,
|
||||||
|
@ -46,13 +44,7 @@ class OverviewData @Inject constructor(
|
||||||
private val activePlugin: ActivePlugin,
|
private val activePlugin: ActivePlugin,
|
||||||
private val defaultValueHelper: DefaultValueHelper,
|
private val defaultValueHelper: DefaultValueHelper,
|
||||||
private val profileFunction: ProfileFunction,
|
private val profileFunction: ProfileFunction,
|
||||||
private val config: Config,
|
private val repository: AppRepository
|
||||||
private val loop: Loop,
|
|
||||||
private val nsDeviceStatus: NSDeviceStatus,
|
|
||||||
private val repository: AppRepository,
|
|
||||||
private val overviewMenus: OverviewMenus,
|
|
||||||
private val iobCobCalculator: IobCobCalculator,
|
|
||||||
private val translator: Translator
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var rangeToDisplay = 6 // for graph
|
var rangeToDisplay = 6 // for graph
|
||||||
|
@ -62,14 +54,7 @@ class OverviewData @Inject constructor(
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
pumpStatus = ""
|
pumpStatus = ""
|
||||||
calcProgress = ""
|
calcProgressPct = 100
|
||||||
lastBg = null
|
|
||||||
bolusIob = null
|
|
||||||
basalIob = null
|
|
||||||
cobInfo = null
|
|
||||||
lastCarbsTime = 0L
|
|
||||||
temporaryTarget = null
|
|
||||||
lastAutosensData = null
|
|
||||||
bgReadingsArray = ArrayList()
|
bgReadingsArray = ArrayList()
|
||||||
bucketedGraphSeries = PointsWithLabelGraphSeries()
|
bucketedGraphSeries = PointsWithLabelGraphSeries()
|
||||||
bgReadingGraphSeries = PointsWithLabelGraphSeries()
|
bgReadingGraphSeries = PointsWithLabelGraphSeries()
|
||||||
|
@ -120,13 +105,18 @@ class OverviewData @Inject constructor(
|
||||||
* CALC PROGRESS
|
* CALC PROGRESS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var calcProgress: String = ""
|
var calcProgressPct: Int = 100
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BG
|
* BG
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var lastBg: GlucoseValue? = null
|
val lastBg: GlucoseValue?
|
||||||
|
get() =
|
||||||
|
repository.getLastGlucoseValueWrapped().blockingGet().let { gvWrapped ->
|
||||||
|
if (gvWrapped is ValueWrapper.Existing) gvWrapped.value
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
|
||||||
val isLow: Boolean
|
val isLow: Boolean
|
||||||
get() = lastBg?.let { lastBg ->
|
get() = lastBg?.let { lastBg ->
|
||||||
|
@ -138,11 +128,12 @@ class OverviewData @Inject constructor(
|
||||||
lastBg.valueToUnits(profileFunction.getUnits()) > defaultValueHelper.determineHighLine()
|
lastBg.valueToUnits(profileFunction.getUnits()) > defaultValueHelper.determineHighLine()
|
||||||
} ?: false
|
} ?: false
|
||||||
|
|
||||||
val lastBgColor: Int
|
@ColorInt
|
||||||
get() = when {
|
fun lastBgColor(context: Context?): Int =
|
||||||
isLow -> rh.gc(R.color.low)
|
when {
|
||||||
isHigh -> rh.gc(R.color.high)
|
isLow -> rh.gac(context, R.attr.bgLow)
|
||||||
else -> rh.gc(R.color.inrange)
|
isHigh -> rh.gac(context, R.attr.highColor)
|
||||||
|
else -> rh.gac(context, R.attr.bgInRange)
|
||||||
}
|
}
|
||||||
|
|
||||||
val lastBgDescription: String
|
val lastBgDescription: String
|
||||||
|
@ -162,17 +153,16 @@ class OverviewData @Inject constructor(
|
||||||
* TEMPORARY BASAL
|
* TEMPORARY BASAL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
val temporaryBasalText: String
|
fun temporaryBasalText(iobCobCalculator: IobCobCalculator): String =
|
||||||
get() =
|
profileFunction.getProfile()?.let { profile ->
|
||||||
profileFunction.getProfile()?.let { profile ->
|
var temporaryBasal = iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())
|
||||||
var temporaryBasal = iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())
|
if (temporaryBasal?.isInProgress == false) temporaryBasal = null
|
||||||
if (temporaryBasal?.isInProgress == false) temporaryBasal = null
|
temporaryBasal?.let { "T:" + it.toStringShort() }
|
||||||
temporaryBasal?.let { "T:" + it.toStringShort() }
|
?: rh.gs(R.string.pump_basebasalrate, profile.getBasal())
|
||||||
?: rh.gs(R.string.pump_basebasalrate, profile.getBasal())
|
} ?: rh.gs(R.string.notavailable)
|
||||||
} ?: rh.gs(R.string.notavailable)
|
|
||||||
|
|
||||||
val temporaryBasalDialogText: String
|
fun temporaryBasalDialogText(iobCobCalculator: IobCobCalculator): String =
|
||||||
get() = profileFunction.getProfile()?.let { profile ->
|
profileFunction.getProfile()?.let { profile ->
|
||||||
iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let { temporaryBasal ->
|
iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let { temporaryBasal ->
|
||||||
"${rh.gs(R.string.basebasalrate_label)}: ${rh.gs(R.string.pump_basebasalrate, profile.getBasal())}" +
|
"${rh.gs(R.string.basebasalrate_label)}: ${rh.gs(R.string.pump_basebasalrate, profile.getBasal())}" +
|
||||||
"\n" + rh.gs(R.string.tempbasal_label) + ": " + temporaryBasal.toStringFull(profile, dateUtil)
|
"\n" + rh.gs(R.string.tempbasal_label) + ": " + temporaryBasal.toStringFull(profile, dateUtil)
|
||||||
|
@ -180,76 +170,73 @@ class OverviewData @Inject constructor(
|
||||||
?: "${rh.gs(R.string.basebasalrate_label)}: ${rh.gs(R.string.pump_basebasalrate, profile.getBasal())}"
|
?: "${rh.gs(R.string.basebasalrate_label)}: ${rh.gs(R.string.pump_basebasalrate, profile.getBasal())}"
|
||||||
} ?: rh.gs(R.string.notavailable)
|
} ?: rh.gs(R.string.notavailable)
|
||||||
|
|
||||||
val temporaryBasalIcon: Int
|
fun temporaryBasalIcon(iobCobCalculator: IobCobCalculator): Int =
|
||||||
get() =
|
profileFunction.getProfile()?.let { profile ->
|
||||||
profileFunction.getProfile()?.let { profile ->
|
iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let { temporaryBasal ->
|
||||||
iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let { temporaryBasal ->
|
val percentRate = temporaryBasal.convertedToPercent(dateUtil.now(), profile)
|
||||||
val percentRate = temporaryBasal.convertedToPercent(dateUtil.now(), profile)
|
when {
|
||||||
when {
|
percentRate > 100 -> R.drawable.ic_cp_basal_tbr_high
|
||||||
percentRate > 100 -> R.drawable.ic_cp_basal_tbr_high
|
percentRate < 100 -> R.drawable.ic_cp_basal_tbr_low
|
||||||
percentRate < 100 -> R.drawable.ic_cp_basal_tbr_low
|
else -> R.drawable.ic_cp_basal_no_tbr
|
||||||
else -> R.drawable.ic_cp_basal_no_tbr
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} ?: R.drawable.ic_cp_basal_no_tbr
|
}
|
||||||
|
} ?: R.drawable.ic_cp_basal_no_tbr
|
||||||
|
|
||||||
val temporaryBasalColor: Int
|
fun temporaryBasalColor(context: Context?, iobCobCalculator: IobCobCalculator): Int = iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let { rh.gac(context , R.attr.basal) }
|
||||||
get() = iobCobCalculator.getTempBasalIncludingConvertedExtended(dateUtil.now())?.let { rh.gc(R.color.basal) }
|
?: rh.gac(context, R.attr.defaultTextColor)
|
||||||
?: rh.gc(R.color.defaulttextcolor)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EXTENDED BOLUS
|
* EXTENDED BOLUS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
val extendedBolusText: String
|
fun extendedBolusText(iobCobCalculator: IobCobCalculator): String =
|
||||||
get() =
|
iobCobCalculator.getExtendedBolus(dateUtil.now())?.let { extendedBolus ->
|
||||||
iobCobCalculator.getExtendedBolus(dateUtil.now())?.let { extendedBolus ->
|
if (!extendedBolus.isInProgress(dateUtil)) ""
|
||||||
if (!extendedBolus.isInProgress(dateUtil)) ""
|
else if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) rh.gs(R.string.pump_basebasalrate, extendedBolus.rate)
|
||||||
else if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) rh.gs(R.string.pump_basebasalrate, extendedBolus.rate)
|
else ""
|
||||||
else ""
|
} ?: ""
|
||||||
} ?: ""
|
|
||||||
|
|
||||||
val extendedBolusDialogText: String
|
fun extendedBolusDialogText(iobCobCalculator: IobCobCalculator): String =
|
||||||
get() = iobCobCalculator.getExtendedBolus(dateUtil.now())?.toStringFull(dateUtil) ?: ""
|
iobCobCalculator.getExtendedBolus(dateUtil.now())?.toStringFull(dateUtil) ?: ""
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IOB, COB
|
* IOB, COB
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var bolusIob: IobTotal? = null
|
fun bolusIob(iobCobCalculator: IobCobCalculator): IobTotal = iobCobCalculator.calculateIobFromBolus().round()
|
||||||
var basalIob: IobTotal? = null
|
fun basalIob(iobCobCalculator: IobCobCalculator): IobTotal = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round()
|
||||||
var cobInfo: CobInfo? = null
|
fun cobInfo(iobCobCalculator: IobCobCalculator): CobInfo = iobCobCalculator.getCobInfo(true, "Overview COB")
|
||||||
var lastCarbsTime: Long = 0L
|
|
||||||
|
|
||||||
val iobText: String
|
val lastCarbsTime: Long
|
||||||
get() =
|
get() = repository.getLastCarbsRecordWrapped().blockingGet().let { lastCarbs ->
|
||||||
bolusIob?.let { bolusIob ->
|
if (lastCarbs is ValueWrapper.Existing) lastCarbs.value.timestamp else 0L
|
||||||
basalIob?.let { basalIob ->
|
}
|
||||||
rh.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob)
|
|
||||||
} ?: rh.gs(R.string.value_unavailable_short)
|
|
||||||
} ?: rh.gs(R.string.value_unavailable_short)
|
|
||||||
|
|
||||||
val iobDialogText: String
|
fun iobText(iobCobCalculator: IobCobCalculator): String =
|
||||||
get() =
|
rh.gs(R.string.formatinsulinunits, bolusIob(iobCobCalculator).iob + basalIob(iobCobCalculator).basaliob)
|
||||||
bolusIob?.let { bolusIob ->
|
|
||||||
basalIob?.let { basalIob ->
|
fun iobDialogText(iobCobCalculator: IobCobCalculator): String =
|
||||||
rh.gs(R.string.formatinsulinunits, bolusIob.iob + basalIob.basaliob) + "\n" +
|
rh.gs(R.string.formatinsulinunits, bolusIob(iobCobCalculator).iob + basalIob(iobCobCalculator).basaliob) + "\n" +
|
||||||
rh.gs(R.string.bolus) + ": " + rh.gs(R.string.formatinsulinunits, bolusIob.iob) + "\n" +
|
rh.gs(R.string.bolus) + ": " + rh.gs(R.string.formatinsulinunits, bolusIob(iobCobCalculator).iob) + "\n" +
|
||||||
rh.gs(R.string.basal) + ": " + rh.gs(R.string.formatinsulinunits, basalIob.basaliob)
|
rh.gs(R.string.basal) + ": " + rh.gs(R.string.formatinsulinunits, basalIob(iobCobCalculator).basaliob)
|
||||||
} ?: rh.gs(R.string.value_unavailable_short)
|
|
||||||
} ?: rh.gs(R.string.value_unavailable_short)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TEMP TARGET
|
* TEMP TARGET
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var temporaryTarget: TemporaryTarget? = null
|
val temporaryTarget: TemporaryTarget?
|
||||||
|
get() =
|
||||||
|
repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet().let { tempTarget ->
|
||||||
|
if (tempTarget is ValueWrapper.Existing) tempTarget.value
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SENSITIVITY
|
* SENSITIVITY
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var lastAutosensData: AutosensData? = null
|
fun lastAutosensData(iobCobCalculator: IobCobCalculator) = iobCobCalculator.ads.getLastAutosensData("Overview", aapsLogger, dateUtil)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Graphs
|
* Graphs
|
||||||
*/
|
*/
|
||||||
|
@ -276,6 +263,8 @@ class OverviewData @Inject constructor(
|
||||||
|
|
||||||
var maxTreatmentsValue = 0.0
|
var maxTreatmentsValue = 0.0
|
||||||
var treatmentsSeries: PointsWithLabelGraphSeries<DataPointWithLabelInterface> = PointsWithLabelGraphSeries()
|
var treatmentsSeries: PointsWithLabelGraphSeries<DataPointWithLabelInterface> = PointsWithLabelGraphSeries()
|
||||||
|
var maxTherapyEventValue = 0.0
|
||||||
|
var therapyEventSeries: PointsWithLabelGraphSeries<DataPointWithLabelInterface> = PointsWithLabelGraphSeries()
|
||||||
|
|
||||||
var maxIobValueFound = Double.MIN_VALUE
|
var maxIobValueFound = Double.MIN_VALUE
|
||||||
val iobScale = Scale()
|
val iobScale = Scale()
|
||||||
|
@ -309,532 +298,4 @@ class OverviewData @Inject constructor(
|
||||||
val dsMinScale = Scale()
|
val dsMinScale = Scale()
|
||||||
var dsMaxSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
|
var dsMaxSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
|
||||||
var dsMinSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
|
var dsMinSeries: LineGraphSeries<ScaledDataPoint> = LineGraphSeries()
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
@Suppress("SameParameterValue", "UNUSED_PARAMETER")
|
|
||||||
fun prepareBgData(from: String) {
|
|
||||||
// val start = dateUtil.now()
|
|
||||||
maxBgValue = Double.MIN_VALUE
|
|
||||||
bgReadingsArray = repository.compatGetBgReadingsDataFromTime(fromTime, toTime, false).blockingGet()
|
|
||||||
val bgListArray: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
|
||||||
for (bg in bgReadingsArray) {
|
|
||||||
if (bg.timestamp < fromTime || bg.timestamp > toTime) continue
|
|
||||||
if (bg.value > maxBgValue) maxBgValue = bg.value
|
|
||||||
bgListArray.add(GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, rh))
|
|
||||||
}
|
|
||||||
bgListArray.sortWith { o1: DataPointWithLabelInterface, o2: DataPointWithLabelInterface -> o1.x.compareTo(o2.x) }
|
|
||||||
bgReadingGraphSeries = PointsWithLabelGraphSeries(Array(bgListArray.size) { i -> bgListArray[i] })
|
|
||||||
maxBgValue = Profile.fromMgdlToUnits(maxBgValue, profileFunction.getUnits())
|
|
||||||
if (defaultValueHelper.determineHighLine() > maxBgValue) maxBgValue = defaultValueHelper.determineHighLine()
|
|
||||||
maxBgValue = addUpperChartMargin(maxBgValue)
|
|
||||||
// profiler.log(LTag.UI, "prepareBgData() $from", start)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
@Synchronized
|
|
||||||
fun preparePredictions(from: String) {
|
|
||||||
// val start = dateUtil.now()
|
|
||||||
val apsResult = if (config.APS) loop.lastRun?.constraintsProcessed else nsDeviceStatus.getAPSResult(injector)
|
|
||||||
val predictionsAvailable = if (config.APS) loop.lastRun?.request?.hasPredictions == true else config.NSCLIENT
|
|
||||||
val menuChartSettings = overviewMenus.setting
|
|
||||||
// align to hours
|
|
||||||
val calendar = Calendar.getInstance().also {
|
|
||||||
it.timeInMillis = System.currentTimeMillis()
|
|
||||||
it[Calendar.MILLISECOND] = 0
|
|
||||||
it[Calendar.SECOND] = 0
|
|
||||||
it[Calendar.MINUTE] = 0
|
|
||||||
it.add(Calendar.HOUR, 1)
|
|
||||||
}
|
|
||||||
if (predictionsAvailable && apsResult != null && menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal]) {
|
|
||||||
var predictionHours = (ceil(apsResult.latestPredictionsTime - System.currentTimeMillis().toDouble()) / (60 * 60 * 1000)).toInt()
|
|
||||||
predictionHours = min(2, predictionHours)
|
|
||||||
predictionHours = max(0, predictionHours)
|
|
||||||
val hoursToFetch = rangeToDisplay - predictionHours
|
|
||||||
toTime = calendar.timeInMillis + 100000 // little bit more to avoid wrong rounding - GraphView specific
|
|
||||||
fromTime = toTime - T.hours(hoursToFetch.toLong()).msecs()
|
|
||||||
endTime = toTime + T.hours(predictionHours.toLong()).msecs()
|
|
||||||
} else {
|
|
||||||
toTime = calendar.timeInMillis + 100000 // little bit more to avoid wrong rounding - GraphView specific
|
|
||||||
fromTime = toTime - T.hours(rangeToDisplay.toLong()).msecs()
|
|
||||||
endTime = toTime
|
|
||||||
}
|
|
||||||
|
|
||||||
val bgListArray: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
|
||||||
val predictions: MutableList<GlucoseValueDataPoint>? = apsResult?.predictions
|
|
||||||
?.map { bg -> GlucoseValueDataPoint(bg, defaultValueHelper, profileFunction, rh) }
|
|
||||||
?.toMutableList()
|
|
||||||
if (predictions != null) {
|
|
||||||
predictions.sortWith { o1: GlucoseValueDataPoint, o2: GlucoseValueDataPoint -> o1.x.compareTo(o2.x) }
|
|
||||||
for (prediction in predictions) if (prediction.data.value >= 40) bgListArray.add(prediction)
|
|
||||||
}
|
|
||||||
predictionsGraphSeries = PointsWithLabelGraphSeries(Array(bgListArray.size) { i -> bgListArray[i] })
|
|
||||||
// profiler.log(LTag.UI, "preparePredictions() $from", start)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
@Suppress("SameParameterValue", "UNUSED_PARAMETER")
|
|
||||||
fun prepareBucketedData(from: String) {
|
|
||||||
// val start = dateUtil.now()
|
|
||||||
val bucketedData = iobCobCalculator.ads.getBucketedDataTableCopy() ?: return
|
|
||||||
if (bucketedData.isEmpty()) {
|
|
||||||
aapsLogger.debug("No bucketed data.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val bucketedListArray: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
|
||||||
for (inMemoryGlucoseValue in bucketedData) {
|
|
||||||
if (inMemoryGlucoseValue.timestamp < fromTime || inMemoryGlucoseValue.timestamp > toTime) continue
|
|
||||||
bucketedListArray.add(InMemoryGlucoseValueDataPoint(inMemoryGlucoseValue, profileFunction, rh))
|
|
||||||
}
|
|
||||||
bucketedListArray.sortWith { o1: DataPointWithLabelInterface, o2: DataPointWithLabelInterface -> o1.x.compareTo(o2.x) }
|
|
||||||
bucketedGraphSeries = PointsWithLabelGraphSeries(Array(bucketedListArray.size) { i -> bucketedListArray[i] })
|
|
||||||
// profiler.log(LTag.UI, "prepareBucketedData() $from", start)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
@Synchronized
|
|
||||||
fun prepareBasalData(from: String) {
|
|
||||||
// val start = dateUtil.now()
|
|
||||||
maxBasalValueFound = 0.0
|
|
||||||
val baseBasalArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
val tempBasalArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
val basalLineArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
val absoluteBasalLineArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
var lastLineBasal = 0.0
|
|
||||||
var lastAbsoluteLineBasal = -1.0
|
|
||||||
var lastBaseBasal = 0.0
|
|
||||||
var lastTempBasal = 0.0
|
|
||||||
var time = fromTime
|
|
||||||
while (time < toTime) {
|
|
||||||
val profile = profileFunction.getProfile(time)
|
|
||||||
if (profile == null) {
|
|
||||||
time += 60 * 1000L
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
val basalData = iobCobCalculator.getBasalData(profile, time)
|
|
||||||
val baseBasalValue = basalData.basal
|
|
||||||
var absoluteLineValue = baseBasalValue
|
|
||||||
var tempBasalValue = 0.0
|
|
||||||
var basal = 0.0
|
|
||||||
if (basalData.isTempBasalRunning) {
|
|
||||||
tempBasalValue = basalData.tempBasalAbsolute
|
|
||||||
absoluteLineValue = tempBasalValue
|
|
||||||
if (tempBasalValue != lastTempBasal) {
|
|
||||||
tempBasalArray.add(ScaledDataPoint(time, lastTempBasal, basalScale))
|
|
||||||
tempBasalArray.add(ScaledDataPoint(time, tempBasalValue.also { basal = it }, basalScale))
|
|
||||||
}
|
|
||||||
if (lastBaseBasal != 0.0) {
|
|
||||||
baseBasalArray.add(ScaledDataPoint(time, lastBaseBasal, basalScale))
|
|
||||||
baseBasalArray.add(ScaledDataPoint(time, 0.0, basalScale))
|
|
||||||
lastBaseBasal = 0.0
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (baseBasalValue != lastBaseBasal) {
|
|
||||||
baseBasalArray.add(ScaledDataPoint(time, lastBaseBasal, basalScale))
|
|
||||||
baseBasalArray.add(ScaledDataPoint(time, baseBasalValue.also { basal = it }, basalScale))
|
|
||||||
lastBaseBasal = baseBasalValue
|
|
||||||
}
|
|
||||||
if (lastTempBasal != 0.0) {
|
|
||||||
tempBasalArray.add(ScaledDataPoint(time, lastTempBasal, basalScale))
|
|
||||||
tempBasalArray.add(ScaledDataPoint(time, 0.0, basalScale))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (baseBasalValue != lastLineBasal) {
|
|
||||||
basalLineArray.add(ScaledDataPoint(time, lastLineBasal, basalScale))
|
|
||||||
basalLineArray.add(ScaledDataPoint(time, baseBasalValue, basalScale))
|
|
||||||
}
|
|
||||||
if (absoluteLineValue != lastAbsoluteLineBasal) {
|
|
||||||
absoluteBasalLineArray.add(ScaledDataPoint(time, lastAbsoluteLineBasal, basalScale))
|
|
||||||
absoluteBasalLineArray.add(ScaledDataPoint(time, basal, basalScale))
|
|
||||||
}
|
|
||||||
lastAbsoluteLineBasal = absoluteLineValue
|
|
||||||
lastLineBasal = baseBasalValue
|
|
||||||
lastTempBasal = tempBasalValue
|
|
||||||
maxBasalValueFound = max(maxBasalValueFound, max(tempBasalValue, baseBasalValue))
|
|
||||||
time += 60 * 1000L
|
|
||||||
}
|
|
||||||
|
|
||||||
// final points
|
|
||||||
basalLineArray.add(ScaledDataPoint(toTime, lastLineBasal, basalScale))
|
|
||||||
baseBasalArray.add(ScaledDataPoint(toTime, lastBaseBasal, basalScale))
|
|
||||||
tempBasalArray.add(ScaledDataPoint(toTime, lastTempBasal, basalScale))
|
|
||||||
absoluteBasalLineArray.add(ScaledDataPoint(toTime, lastAbsoluteLineBasal, basalScale))
|
|
||||||
|
|
||||||
// create series
|
|
||||||
baseBasalGraphSeries = LineGraphSeries(Array(baseBasalArray.size) { i -> baseBasalArray[i] }).also {
|
|
||||||
it.isDrawBackground = true
|
|
||||||
it.backgroundColor = rh.gc(R.color.basebasal)
|
|
||||||
it.thickness = 0
|
|
||||||
}
|
|
||||||
tempBasalGraphSeries = LineGraphSeries(Array(tempBasalArray.size) { i -> tempBasalArray[i] }).also {
|
|
||||||
it.isDrawBackground = true
|
|
||||||
it.backgroundColor = rh.gc(R.color.tempbasal)
|
|
||||||
it.thickness = 0
|
|
||||||
}
|
|
||||||
basalLineGraphSeries = LineGraphSeries(Array(basalLineArray.size) { i -> basalLineArray[i] }).also {
|
|
||||||
it.setCustomPaint(Paint().also { paint ->
|
|
||||||
paint.style = Paint.Style.STROKE
|
|
||||||
paint.strokeWidth = rh.getDisplayMetrics().scaledDensity * 2
|
|
||||||
paint.pathEffect = DashPathEffect(floatArrayOf(2f, 4f), 0f)
|
|
||||||
paint.color = rh.gc(R.color.basal)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
absoluteBasalGraphSeries = LineGraphSeries(Array(absoluteBasalLineArray.size) { i -> absoluteBasalLineArray[i] }).also {
|
|
||||||
it.setCustomPaint(Paint().also { absolutePaint ->
|
|
||||||
absolutePaint.style = Paint.Style.STROKE
|
|
||||||
absolutePaint.strokeWidth = rh.getDisplayMetrics().scaledDensity * 2
|
|
||||||
absolutePaint.color = rh.gc(R.color.basal)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// profiler.log(LTag.UI, "prepareBasalData() $from", start)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
@Synchronized
|
|
||||||
fun prepareTemporaryTargetData(from: String) {
|
|
||||||
// val start = dateUtil.now()
|
|
||||||
val profile = profileFunction.getProfile() ?: return
|
|
||||||
val units = profileFunction.getUnits()
|
|
||||||
var toTime = toTime
|
|
||||||
val targetsSeriesArray: MutableList<DataPoint> = java.util.ArrayList()
|
|
||||||
var lastTarget = -1.0
|
|
||||||
loop.lastRun?.constraintsProcessed?.let { toTime = max(it.latestPredictionsTime, toTime) }
|
|
||||||
var time = fromTime
|
|
||||||
while (time < toTime) {
|
|
||||||
val tt = repository.getTemporaryTargetActiveAt(time).blockingGet()
|
|
||||||
val value: Double = if (tt is ValueWrapper.Existing) {
|
|
||||||
Profile.fromMgdlToUnits(tt.value.target(), units)
|
|
||||||
} else {
|
|
||||||
Profile.fromMgdlToUnits((profile.getTargetLowMgdl(time) + profile.getTargetHighMgdl(time)) / 2, units)
|
|
||||||
}
|
|
||||||
if (lastTarget != value) {
|
|
||||||
if (lastTarget != -1.0) targetsSeriesArray.add(DataPoint(time.toDouble(), lastTarget))
|
|
||||||
targetsSeriesArray.add(DataPoint(time.toDouble(), value))
|
|
||||||
}
|
|
||||||
lastTarget = value
|
|
||||||
time += 5 * 60 * 1000L
|
|
||||||
}
|
|
||||||
// final point
|
|
||||||
targetsSeriesArray.add(DataPoint(toTime.toDouble(), lastTarget))
|
|
||||||
// create series
|
|
||||||
temporaryTargetSeries = LineGraphSeries(Array(targetsSeriesArray.size) { i -> targetsSeriesArray[i] }).also {
|
|
||||||
it.isDrawBackground = false
|
|
||||||
it.color = rh.gc(R.color.tempTargetBackground)
|
|
||||||
it.thickness = 2
|
|
||||||
}
|
|
||||||
// profiler.log(LTag.UI, "prepareTemporaryTargetData() $from", start)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
@Synchronized
|
|
||||||
fun prepareTreatmentsData(from: String) {
|
|
||||||
// val start = dateUtil.now()
|
|
||||||
maxTreatmentsValue = 0.0
|
|
||||||
val filteredTreatments: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
|
||||||
repository.getBolusesDataFromTimeToTime(fromTime, endTime, true).blockingGet()
|
|
||||||
.map { BolusDataPoint(it, rh, activePlugin, defaultValueHelper) }
|
|
||||||
.filter { it.data.type == Bolus.Type.NORMAL || it.data.type == Bolus.Type.SMB }
|
|
||||||
.forEach {
|
|
||||||
it.y = getNearestBg(it.x.toLong())
|
|
||||||
filteredTreatments.add(it)
|
|
||||||
}
|
|
||||||
repository.getCarbsDataFromTimeToTimeExpanded(fromTime, endTime, true).blockingGet()
|
|
||||||
.map { CarbsDataPoint(it, rh) }
|
|
||||||
.forEach {
|
|
||||||
it.y = getNearestBg(it.x.toLong())
|
|
||||||
filteredTreatments.add(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProfileSwitch
|
|
||||||
repository.getEffectiveProfileSwitchDataFromTimeToTime(fromTime, endTime, true).blockingGet()
|
|
||||||
.map { EffectiveProfileSwitchDataPoint(it) }
|
|
||||||
.forEach(filteredTreatments::add)
|
|
||||||
|
|
||||||
// OfflineEvent
|
|
||||||
repository.getOfflineEventDataFromTimeToTime(fromTime, endTime, true).blockingGet()
|
|
||||||
.map {
|
|
||||||
TherapyEventDataPoint(
|
|
||||||
TherapyEvent(timestamp = it.timestamp, duration = it.duration, type = TherapyEvent.Type.APS_OFFLINE, glucoseUnit = TherapyEvent.GlucoseUnit.MMOL),
|
|
||||||
rh,
|
|
||||||
profileFunction,
|
|
||||||
translator
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.forEach(filteredTreatments::add)
|
|
||||||
|
|
||||||
// Extended bolus
|
|
||||||
if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) {
|
|
||||||
repository.getExtendedBolusDataFromTimeToTime(fromTime, endTime, true).blockingGet()
|
|
||||||
.map { ExtendedBolusDataPoint(it) }
|
|
||||||
.filter { it.duration != 0L }
|
|
||||||
.forEach {
|
|
||||||
it.y = getNearestBg(it.x.toLong())
|
|
||||||
filteredTreatments.add(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Careportal
|
|
||||||
repository.compatGetTherapyEventDataFromToTime(fromTime - T.hours(6).msecs(), endTime).blockingGet()
|
|
||||||
.map { TherapyEventDataPoint(it, rh, profileFunction, translator) }
|
|
||||||
.filterTimeframe(fromTime, endTime)
|
|
||||||
.forEach {
|
|
||||||
if (it.y == 0.0) it.y = getNearestBg(it.x.toLong())
|
|
||||||
filteredTreatments.add(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
// increase maxY if a treatment forces it's own height that's higher than a BG value
|
|
||||||
filteredTreatments.map { it.y }
|
|
||||||
.maxOrNull()
|
|
||||||
?.let(::addUpperChartMargin)
|
|
||||||
?.let { maxTreatmentsValue = maxOf(maxTreatmentsValue, it) }
|
|
||||||
|
|
||||||
treatmentsSeries = PointsWithLabelGraphSeries(filteredTreatments.toTypedArray())
|
|
||||||
// profiler.log(LTag.UI, "prepareTreatmentsData() $from", start)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
@Synchronized
|
|
||||||
fun prepareIobAutosensData(from: String) {
|
|
||||||
// val start = dateUtil.now()
|
|
||||||
val iobArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
val absIobArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
maxIobValueFound = Double.MIN_VALUE
|
|
||||||
var lastIob = 0.0
|
|
||||||
var absLastIob = 0.0
|
|
||||||
var time = fromTime
|
|
||||||
|
|
||||||
val minFailOverActiveList: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
|
||||||
val cobArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
maxCobValueFound = Double.MIN_VALUE
|
|
||||||
var lastCob = 0
|
|
||||||
|
|
||||||
val actArrayHist: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
val actArrayPrediction: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
val now = dateUtil.now().toDouble()
|
|
||||||
maxIAValue = 0.0
|
|
||||||
|
|
||||||
val bgiArrayHist: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
val bgiArrayPrediction: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
maxBGIValue = Double.MIN_VALUE
|
|
||||||
|
|
||||||
val devArray: MutableList<OverviewPlugin.DeviationDataPoint> = java.util.ArrayList()
|
|
||||||
maxDevValueFound = Double.MIN_VALUE
|
|
||||||
|
|
||||||
val ratioArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
maxRatioValueFound = 5.0 //even if sens data equals 0 for all the period, minimum scale is between 95% and 105%
|
|
||||||
minRatioValueFound = -5.0
|
|
||||||
|
|
||||||
val dsMaxArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
val dsMinArray: MutableList<ScaledDataPoint> = java.util.ArrayList()
|
|
||||||
maxFromMaxValueFound = Double.MIN_VALUE
|
|
||||||
maxFromMinValueFound = Double.MIN_VALUE
|
|
||||||
|
|
||||||
val adsData = iobCobCalculator.ads.clone()
|
|
||||||
|
|
||||||
while (time <= toTime) {
|
|
||||||
val profile = profileFunction.getProfile(time)
|
|
||||||
if (profile == null) {
|
|
||||||
time += 5 * 60 * 1000L
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// IOB
|
|
||||||
val iob = iobCobCalculator.calculateFromTreatmentsAndTemps(time, profile)
|
|
||||||
val baseBasalIob = iobCobCalculator.calculateAbsoluteIobFromBaseBasals(time)
|
|
||||||
val absIob = IobTotal.combine(iob, baseBasalIob)
|
|
||||||
val autosensData = adsData.getAutosensDataAtTime(time)
|
|
||||||
if (abs(lastIob - iob.iob) > 0.02) {
|
|
||||||
if (abs(lastIob - iob.iob) > 0.2) iobArray.add(ScaledDataPoint(time, lastIob, iobScale))
|
|
||||||
iobArray.add(ScaledDataPoint(time, iob.iob, iobScale))
|
|
||||||
maxIobValueFound = maxOf(maxIobValueFound, abs(iob.iob))
|
|
||||||
lastIob = iob.iob
|
|
||||||
}
|
|
||||||
if (abs(absLastIob - absIob.iob) > 0.02) {
|
|
||||||
if (abs(absLastIob - absIob.iob) > 0.2) absIobArray.add(ScaledDataPoint(time, absLastIob, iobScale))
|
|
||||||
absIobArray.add(ScaledDataPoint(time, absIob.iob, iobScale))
|
|
||||||
maxIobValueFound = maxOf(maxIobValueFound, abs(absIob.iob))
|
|
||||||
absLastIob = absIob.iob
|
|
||||||
}
|
|
||||||
|
|
||||||
// COB
|
|
||||||
if (autosensData != null) {
|
|
||||||
val cob = autosensData.cob.toInt()
|
|
||||||
if (cob != lastCob) {
|
|
||||||
if (autosensData.carbsFromBolus > 0) cobArray.add(ScaledDataPoint(time, lastCob.toDouble(), cobScale))
|
|
||||||
cobArray.add(ScaledDataPoint(time, cob.toDouble(), cobScale))
|
|
||||||
maxCobValueFound = max(maxCobValueFound, cob.toDouble())
|
|
||||||
lastCob = cob
|
|
||||||
}
|
|
||||||
if (autosensData.failOverToMinAbsorptionRate) {
|
|
||||||
autosensData.scale = cobScale
|
|
||||||
autosensData.chartTime = time
|
|
||||||
minFailOverActiveList.add(autosensData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ACTIVITY
|
|
||||||
if (time <= now) actArrayHist.add(ScaledDataPoint(time, iob.activity, actScale))
|
|
||||||
else actArrayPrediction.add(ScaledDataPoint(time, iob.activity, actScale))
|
|
||||||
maxIAValue = max(maxIAValue, abs(iob.activity))
|
|
||||||
|
|
||||||
// BGI
|
|
||||||
val devBgiScale = overviewMenus.isEnabledIn(OverviewMenus.CharType.DEV) == overviewMenus.isEnabledIn(OverviewMenus.CharType.BGI)
|
|
||||||
val deviation = if (devBgiScale) autosensData?.deviation ?: 0.0 else 0.0
|
|
||||||
val bgi: Double = iob.activity * profile.getIsfMgdl(time) * 5.0
|
|
||||||
if (time <= now) bgiArrayHist.add(ScaledDataPoint(time, bgi, bgiScale))
|
|
||||||
else bgiArrayPrediction.add(ScaledDataPoint(time, bgi, bgiScale))
|
|
||||||
maxBGIValue = max(maxBGIValue, max(abs(bgi), deviation))
|
|
||||||
|
|
||||||
// DEVIATIONS
|
|
||||||
if (autosensData != null) {
|
|
||||||
var color = rh.gc(R.color.deviationblack) // "="
|
|
||||||
if (autosensData.type == "" || autosensData.type == "non-meal") {
|
|
||||||
if (autosensData.pastSensitivity == "C") color = rh.gc(R.color.deviationgrey)
|
|
||||||
if (autosensData.pastSensitivity == "+") color = rh.gc(R.color.deviationgreen)
|
|
||||||
if (autosensData.pastSensitivity == "-") color = rh.gc(R.color.deviationred)
|
|
||||||
} else if (autosensData.type == "uam") {
|
|
||||||
color = rh.gc(R.color.uam)
|
|
||||||
} else if (autosensData.type == "csf") {
|
|
||||||
color = rh.gc(R.color.deviationgrey)
|
|
||||||
}
|
|
||||||
devArray.add(OverviewPlugin.DeviationDataPoint(time.toDouble(), autosensData.deviation, color, devScale))
|
|
||||||
maxDevValueFound = maxOf(maxDevValueFound, abs(autosensData.deviation), abs(bgi))
|
|
||||||
}
|
|
||||||
|
|
||||||
// RATIO
|
|
||||||
if (autosensData != null) {
|
|
||||||
ratioArray.add(ScaledDataPoint(time, 100.0 * (autosensData.autosensResult.ratio - 1), ratioScale))
|
|
||||||
maxRatioValueFound = max(maxRatioValueFound, 100.0 * (autosensData.autosensResult.ratio - 1))
|
|
||||||
minRatioValueFound = min(minRatioValueFound, 100.0 * (autosensData.autosensResult.ratio - 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEV SLOPE
|
|
||||||
if (autosensData != null) {
|
|
||||||
dsMaxArray.add(ScaledDataPoint(time, autosensData.slopeFromMaxDeviation, dsMaxScale))
|
|
||||||
dsMinArray.add(ScaledDataPoint(time, autosensData.slopeFromMinDeviation, dsMinScale))
|
|
||||||
maxFromMaxValueFound = max(maxFromMaxValueFound, abs(autosensData.slopeFromMaxDeviation))
|
|
||||||
maxFromMinValueFound = max(maxFromMinValueFound, abs(autosensData.slopeFromMinDeviation))
|
|
||||||
}
|
|
||||||
|
|
||||||
time += 5 * 60 * 1000L
|
|
||||||
}
|
|
||||||
// IOB
|
|
||||||
iobSeries = FixedLineGraphSeries(Array(iobArray.size) { i -> iobArray[i] }).also {
|
|
||||||
it.isDrawBackground = true
|
|
||||||
it.backgroundColor = -0x7f000001 and rh.gc(R.color.iob) //50%
|
|
||||||
it.color = rh.gc(R.color.iob)
|
|
||||||
it.thickness = 3
|
|
||||||
}
|
|
||||||
absIobSeries = FixedLineGraphSeries(Array(absIobArray.size) { i -> absIobArray[i] }).also {
|
|
||||||
it.isDrawBackground = true
|
|
||||||
it.backgroundColor = -0x7f000001 and rh.gc(R.color.iob) //50%
|
|
||||||
it.color = rh.gc(R.color.iob)
|
|
||||||
it.thickness = 3
|
|
||||||
}
|
|
||||||
|
|
||||||
if (overviewMenus.setting[0][OverviewMenus.CharType.PRE.ordinal]) {
|
|
||||||
val autosensData = adsData.getLastAutosensData("GraphData", aapsLogger, dateUtil)
|
|
||||||
val lastAutosensResult = autosensData?.autosensResult ?: AutosensResult()
|
|
||||||
val isTempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing
|
|
||||||
val iobPrediction: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
|
||||||
val iobPredictionArray = iobCobCalculator.calculateIobArrayForSMB(lastAutosensResult, SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget)
|
|
||||||
for (i in iobPredictionArray) {
|
|
||||||
iobPrediction.add(i.setColor(rh.gc(R.color.iobPredAS)))
|
|
||||||
maxIobValueFound = max(maxIobValueFound, abs(i.iob))
|
|
||||||
}
|
|
||||||
iobPredictions1Series = PointsWithLabelGraphSeries(Array(iobPrediction.size) { i -> iobPrediction[i] })
|
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "IOB prediction for AS=" + DecimalFormatter.to2Decimal(lastAutosensResult.ratio) + ": " + iobCobCalculator.iobArrayToString(iobPredictionArray))
|
|
||||||
/*
|
|
||||||
val iobPrediction2: MutableList<DataPointWithLabelInterface> = java.util.ArrayList()
|
|
||||||
val iobPredictionArray2 = iobCobCalculator.calculateIobArrayForSMB(AutosensResult(), SMBDefaults.exercise_mode, SMBDefaults.half_basal_exercise_target, isTempTarget)
|
|
||||||
for (i in iobPredictionArray2) {
|
|
||||||
iobPrediction2.add(i.setColor(rh.gc(R.color.iobPred)))
|
|
||||||
maxIobValueFound = max(maxIobValueFound, abs(i.iob))
|
|
||||||
}
|
|
||||||
iobPredictions2Series = PointsWithLabelGraphSeries(Array(iobPrediction2.size) { i -> iobPrediction2[i] })
|
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "IOB prediction for AS=" + DecimalFormatter.to2Decimal(1.0) + ": " + iobCobCalculator.iobArrayToString(iobPredictionArray2))
|
|
||||||
*/
|
|
||||||
} else {
|
|
||||||
iobPredictions1Series = PointsWithLabelGraphSeries()
|
|
||||||
//iobPredictions2Series = PointsWithLabelGraphSeries()
|
|
||||||
}
|
|
||||||
|
|
||||||
// COB
|
|
||||||
cobSeries = FixedLineGraphSeries(Array(cobArray.size) { i -> cobArray[i] }).also {
|
|
||||||
it.isDrawBackground = true
|
|
||||||
it.backgroundColor = -0x7f000001 and rh.gc(R.color.cob) //50%
|
|
||||||
it.color = rh.gc(R.color.cob)
|
|
||||||
it.thickness = 3
|
|
||||||
}
|
|
||||||
cobMinFailOverSeries = PointsWithLabelGraphSeries(Array(minFailOverActiveList.size) { i -> minFailOverActiveList[i] })
|
|
||||||
|
|
||||||
// ACTIVITY
|
|
||||||
activitySeries = FixedLineGraphSeries(Array(actArrayHist.size) { i -> actArrayHist[i] }).also {
|
|
||||||
it.isDrawBackground = false
|
|
||||||
it.color = rh.gc(R.color.activity)
|
|
||||||
it.thickness = 3
|
|
||||||
}
|
|
||||||
activityPredictionSeries = FixedLineGraphSeries(Array(actArrayPrediction.size) { i -> actArrayPrediction[i] }).also {
|
|
||||||
it.setCustomPaint(Paint().also { paint ->
|
|
||||||
paint.style = Paint.Style.STROKE
|
|
||||||
paint.strokeWidth = 3f
|
|
||||||
paint.pathEffect = DashPathEffect(floatArrayOf(4f, 4f), 0f)
|
|
||||||
paint.color = rh.gc(R.color.activity)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// BGI
|
|
||||||
minusBgiSeries = FixedLineGraphSeries(Array(bgiArrayHist.size) { i -> bgiArrayHist[i] }).also {
|
|
||||||
it.isDrawBackground = false
|
|
||||||
it.color = rh.gc(R.color.bgi)
|
|
||||||
it.thickness = 3
|
|
||||||
}
|
|
||||||
minusBgiHistSeries = FixedLineGraphSeries(Array(bgiArrayPrediction.size) { i -> bgiArrayPrediction[i] }).also {
|
|
||||||
it.setCustomPaint(Paint().also { paint ->
|
|
||||||
paint.style = Paint.Style.STROKE
|
|
||||||
paint.strokeWidth = 3f
|
|
||||||
paint.pathEffect = DashPathEffect(floatArrayOf(4f, 4f), 0f)
|
|
||||||
paint.color = rh.gc(R.color.bgi)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEVIATIONS
|
|
||||||
deviationsSeries = BarGraphSeries(Array(devArray.size) { i -> devArray[i] }).also {
|
|
||||||
it.setValueDependentColor { data: OverviewPlugin.DeviationDataPoint -> data.color }
|
|
||||||
}
|
|
||||||
|
|
||||||
// RATIO
|
|
||||||
ratioSeries = LineGraphSeries(Array(ratioArray.size) { i -> ratioArray[i] }).also {
|
|
||||||
it.color = rh.gc(R.color.ratio)
|
|
||||||
it.thickness = 3
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEV SLOPE
|
|
||||||
dsMaxSeries = LineGraphSeries(Array(dsMaxArray.size) { i -> dsMaxArray[i] }).also {
|
|
||||||
it.color = rh.gc(R.color.devslopepos)
|
|
||||||
it.thickness = 3
|
|
||||||
}
|
|
||||||
dsMinSeries = LineGraphSeries(Array(dsMinArray.size) { i -> dsMinArray[i] }).also {
|
|
||||||
it.color = rh.gc(R.color.devslopeneg)
|
|
||||||
it.thickness = 3
|
|
||||||
}
|
|
||||||
|
|
||||||
// profiler.log(LTag.UI, "prepareIobAutosensData() $from", start)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addUpperChartMargin(maxBgValue: Double) =
|
|
||||||
if (profileFunction.getUnits() == GlucoseUnit.MGDL) Round.roundTo(maxBgValue, 40.0) + 80 else Round.roundTo(maxBgValue, 2.0) + 4
|
|
||||||
|
|
||||||
private fun getNearestBg(date: Long): Double {
|
|
||||||
bgReadingsArray.let { bgReadingsArray ->
|
|
||||||
for (reading in bgReadingsArray) {
|
|
||||||
if (reading.timestamp > date) continue
|
|
||||||
return Profile.fromMgdlToUnits(reading.value, profileFunction.getUnits())
|
|
||||||
}
|
|
||||||
return if (bgReadingsArray.isNotEmpty()) Profile.fromMgdlToUnits(bgReadingsArray[0].value, profileFunction.getUnits())
|
|
||||||
else Profile.fromMgdlToUnits(100.0, profileFunction.getUnits())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <E : DataPointWithLabelInterface> List<E>.filterTimeframe(fromTime: Long, endTime: Long): List<E> =
|
|
||||||
filter { it.x + it.duration >= fromTime && it.x <= endTime }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,9 @@ import android.app.NotificationManager
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
|
import android.graphics.PorterDuff
|
||||||
|
import android.graphics.PorterDuffColorFilter
|
||||||
import android.graphics.drawable.AnimationDrawable
|
import android.graphics.drawable.AnimationDrawable
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
@ -35,17 +36,12 @@ import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
||||||
import info.nightscout.androidaps.database.interfaces.end
|
import info.nightscout.androidaps.database.interfaces.end
|
||||||
import info.nightscout.androidaps.databinding.OverviewFragmentBinding
|
import info.nightscout.androidaps.databinding.OverviewFragmentBinding
|
||||||
import info.nightscout.androidaps.dialogs.*
|
import info.nightscout.androidaps.dialogs.*
|
||||||
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange
|
import info.nightscout.androidaps.events.*
|
||||||
import info.nightscout.androidaps.events.EventInitializationChanged
|
|
||||||
import info.nightscout.androidaps.events.EventPreferenceChange
|
|
||||||
import info.nightscout.androidaps.events.EventPumpStatusChanged
|
|
||||||
import info.nightscout.androidaps.events.EventRefreshOverview
|
|
||||||
import info.nightscout.androidaps.extensions.directionToIcon
|
import info.nightscout.androidaps.extensions.directionToIcon
|
||||||
import info.nightscout.androidaps.extensions.isInProgress
|
import info.nightscout.androidaps.extensions.runOnUiThread
|
||||||
import info.nightscout.androidaps.extensions.toVisibility
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.extensions.valueToUnitsString
|
import info.nightscout.androidaps.extensions.valueToUnitsString
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification
|
import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotification
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
|
import info.nightscout.androidaps.plugins.aps.openAPSSMB.DetermineBasalResultSMB
|
||||||
|
@ -61,6 +57,7 @@ import info.nightscout.androidaps.plugins.general.overview.notifications.Notific
|
||||||
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
|
import info.nightscout.androidaps.plugins.general.wear.events.EventWearInitiateAction
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
|
||||||
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpType
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.eros.OmnipodErosPumpPlugin
|
||||||
import info.nightscout.androidaps.plugins.source.DexcomPlugin
|
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.skins.SkinProvider
|
import info.nightscout.androidaps.skins.SkinProvider
|
||||||
|
@ -74,16 +71,16 @@ import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
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.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
|
||||||
import info.nightscout.androidaps.utils.ui.SingleClickButton
|
import info.nightscout.androidaps.utils.ui.SingleClickButton
|
||||||
import info.nightscout.androidaps.utils.ui.UIRunnable
|
import info.nightscout.androidaps.utils.ui.UIRunnable
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
|
@ -150,10 +147,11 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
_binding = it
|
_binding = it
|
||||||
//check screen width
|
//check screen width
|
||||||
dm = DisplayMetrics()
|
dm = DisplayMetrics()
|
||||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R)
|
@Suppress("DEPRECATION")
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
|
||||||
activity?.display?.getRealMetrics(dm)
|
activity?.display?.getRealMetrics(dm)
|
||||||
else
|
else
|
||||||
@Suppress("DEPRECATION") activity?.windowManager?.defaultDisplay?.getMetrics(dm)
|
activity?.windowManager?.defaultDisplay?.getMetrics(dm)
|
||||||
}.root
|
}.root
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
@ -166,13 +164,13 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
smallHeight = screenHeight <= Constants.SMALL_HEIGHT
|
smallHeight = screenHeight <= Constants.SMALL_HEIGHT
|
||||||
val landscape = screenHeight < screenWidth
|
val landscape = screenHeight < screenWidth
|
||||||
|
|
||||||
skinProvider.activeSkin().preProcessLandscapeOverviewLayout(dm, view, landscape, rh.gb(R.bool.isTablet), smallHeight)
|
skinProvider.activeSkin().preProcessLandscapeOverviewLayout(dm, binding, landscape, rh.gb(R.bool.isTablet), smallHeight)
|
||||||
binding.nsclientLayout.visibility = config.NSCLIENT.toVisibility()
|
binding.nsclientLayout.visibility = config.NSCLIENT.toVisibility()
|
||||||
|
|
||||||
binding.notifications.setHasFixedSize(false)
|
binding.notifications.setHasFixedSize(false)
|
||||||
binding.notifications.layoutManager = LinearLayoutManager(view.context)
|
binding.notifications.layoutManager = LinearLayoutManager(view.context)
|
||||||
axisWidth = if (dm.densityDpi <= 120) 3 else if (dm.densityDpi <= 160) 10 else if (dm.densityDpi <= 320) 35 else if (dm.densityDpi <= 420) 50 else if (dm.densityDpi <= 560) 70 else 80
|
axisWidth = if (dm.densityDpi <= 120) 3 else if (dm.densityDpi <= 160) 10 else if (dm.densityDpi <= 320) 35 else if (dm.densityDpi <= 420) 50 else if (dm.densityDpi <= 560) 70 else 80
|
||||||
binding.graphsLayout.bgGraph.gridLabelRenderer?.gridColor = rh.gc(R.color.graphgrid)
|
binding.graphsLayout.bgGraph.gridLabelRenderer?.gridColor = rh.gac(context, R.attr.graphgrid)
|
||||||
binding.graphsLayout.bgGraph.gridLabelRenderer?.reloadStyles()
|
binding.graphsLayout.bgGraph.gridLabelRenderer?.reloadStyles()
|
||||||
binding.graphsLayout.bgGraph.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
binding.graphsLayout.bgGraph.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
||||||
binding.graphsLayout.bgGraph.layoutParams?.height = rh.dpToPx(skinProvider.activeSkin().mainGraphHeight)
|
binding.graphsLayout.bgGraph.layoutParams?.height = rh.dpToPx(skinProvider.activeSkin().mainGraphHeight)
|
||||||
|
@ -186,16 +184,12 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
overviewData.rangeToDisplay += 6
|
overviewData.rangeToDisplay += 6
|
||||||
overviewData.rangeToDisplay = if (overviewData.rangeToDisplay > 24) 6 else overviewData.rangeToDisplay
|
overviewData.rangeToDisplay = if (overviewData.rangeToDisplay > 24) 6 else overviewData.rangeToDisplay
|
||||||
sp.putInt(R.string.key_rangetodisplay, overviewData.rangeToDisplay)
|
sp.putInt(R.string.key_rangetodisplay, overviewData.rangeToDisplay)
|
||||||
overviewData.initRange()
|
|
||||||
overviewData.prepareBucketedData("EventBucketedDataCreated")
|
|
||||||
overviewData.prepareBgData("EventBucketedDataCreated")
|
|
||||||
updateGraph("rangeChange")
|
|
||||||
rxBus.send(EventPreferenceChange(rh, R.string.key_rangetodisplay))
|
rxBus.send(EventPreferenceChange(rh, R.string.key_rangetodisplay))
|
||||||
sp.putBoolean(R.string.key_objectiveusescale, true)
|
sp.putBoolean(R.string.key_objectiveusescale, true)
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
prepareGraphsIfNeeded(overviewMenus.setting.size)
|
prepareGraphsIfNeeded(overviewMenus.setting.size)
|
||||||
overviewMenus.setupChartMenu(binding.graphsLayout.chartMenuButton)
|
context?.let { overviewMenus.setupChartMenu(it, binding.graphsLayout.chartMenuButton) }
|
||||||
|
|
||||||
binding.activeProfile.setOnClickListener(this)
|
binding.activeProfile.setOnClickListener(this)
|
||||||
binding.activeProfile.setOnLongClickListener(this)
|
binding.activeProfile.setOnLongClickListener(this)
|
||||||
|
@ -225,113 +219,107 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
disposable += activePlugin.activeOverview.overviewBus
|
|
||||||
.toObservable(EventUpdateOverviewTime::class.java)
|
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribe({ updateTime(it.from) }, fabricPrivacy::logException)
|
|
||||||
disposable += activePlugin.activeOverview.overviewBus
|
disposable += activePlugin.activeOverview.overviewBus
|
||||||
.toObservable(EventUpdateOverviewCalcProgress::class.java)
|
.toObservable(EventUpdateOverviewCalcProgress::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({ updateCalcProgress(it.from) }, fabricPrivacy::logException)
|
.subscribe({ updateCalcProgress() }, fabricPrivacy::logException)
|
||||||
disposable += activePlugin.activeOverview.overviewBus
|
|
||||||
.toObservable(EventUpdateOverviewProfile::class.java)
|
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribe({ updateProfile(it.from) }, fabricPrivacy::logException)
|
|
||||||
disposable += activePlugin.activeOverview.overviewBus
|
|
||||||
.toObservable(EventUpdateOverviewTemporaryBasal::class.java)
|
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribe({ updateTemporaryBasal(it.from) }, fabricPrivacy::logException)
|
|
||||||
disposable += activePlugin.activeOverview.overviewBus
|
|
||||||
.toObservable(EventUpdateOverviewExtendedBolus::class.java)
|
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribe({ updateExtendedBolus(it.from) }, fabricPrivacy::logException)
|
|
||||||
disposable += activePlugin.activeOverview.overviewBus
|
|
||||||
.toObservable(EventUpdateOverviewTemporaryTarget::class.java)
|
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribe({ updateTemporaryTarget(it.from) }, fabricPrivacy::logException)
|
|
||||||
disposable += activePlugin.activeOverview.overviewBus
|
|
||||||
.toObservable(EventUpdateOverviewBg::class.java)
|
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribe({ updateBg(it.from) }, fabricPrivacy::logException)
|
|
||||||
disposable += activePlugin.activeOverview.overviewBus
|
disposable += activePlugin.activeOverview.overviewBus
|
||||||
.toObservable(EventUpdateOverviewIobCob::class.java)
|
.toObservable(EventUpdateOverviewIobCob::class.java)
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
.debounce(1L, TimeUnit.SECONDS)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({ updateIobCob(it.from) }, fabricPrivacy::logException)
|
.subscribe({ updateIobCob() }, fabricPrivacy::logException)
|
||||||
disposable += activePlugin.activeOverview.overviewBus
|
disposable += activePlugin.activeOverview.overviewBus
|
||||||
.toObservable(EventUpdateOverviewSensitivity::class.java)
|
.toObservable(EventUpdateOverviewSensitivity::class.java)
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
.debounce(1L, TimeUnit.SECONDS)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({ updateSensitivity(it.from) }, fabricPrivacy::logException)
|
.subscribe({ updateSensitivity() }, fabricPrivacy::logException)
|
||||||
disposable += activePlugin.activeOverview.overviewBus
|
disposable += activePlugin.activeOverview.overviewBus
|
||||||
.toObservable(EventUpdateOverviewGraph::class.java)
|
.toObservable(EventUpdateOverviewGraph::class.java)
|
||||||
.debounce(1L, TimeUnit.SECONDS)
|
.debounce(1L, TimeUnit.SECONDS)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({ updateGraph(it.from) }, fabricPrivacy::logException)
|
.subscribe({ updateGraph() }, fabricPrivacy::logException)
|
||||||
disposable += activePlugin.activeOverview.overviewBus
|
disposable += activePlugin.activeOverview.overviewBus
|
||||||
.toObservable(EventUpdateOverviewPumpStatus::class.java)
|
.toObservable(EventUpdateOverviewPumpStatus::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({ updatePumpStatus(it.from) }, fabricPrivacy::logException)
|
.subscribe({ updatePumpStatus() }, fabricPrivacy::logException)
|
||||||
disposable += activePlugin.activeOverview.overviewBus
|
disposable += activePlugin.activeOverview.overviewBus
|
||||||
.toObservable(EventUpdateOverviewNotification::class.java)
|
.toObservable(EventUpdateOverviewNotification::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.subscribe({ updateNotification(it.from) }, fabricPrivacy::logException)
|
.subscribe({ updateNotification() }, fabricPrivacy::logException)
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventNewBG::class.java)
|
||||||
|
.debounce(1L, TimeUnit.SECONDS)
|
||||||
|
.observeOn(aapsSchedulers.main)
|
||||||
|
.subscribe({ updateBg() }, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventRefreshOverview::class.java)
|
.toObservable(EventRefreshOverview::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
if (it.now) overviewPlugin.refreshLoop(it.from)
|
if (it.now) refreshAll()
|
||||||
else scheduleUpdateGUI(it.from)
|
else scheduleUpdateGUI()
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventAcceptOpenLoopChange::class.java)
|
.toObservable(EventAcceptOpenLoopChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ scheduleUpdateGUI("EventAcceptOpenLoopChange") }, fabricPrivacy::logException)
|
.subscribe({ scheduleUpdateGUI() }, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventInitializationChanged::class.java)
|
|
||||||
.observeOn(aapsSchedulers.main)
|
|
||||||
.subscribe({ updateTime("EventInitializationChanged") }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventPreferenceChange::class.java)
|
.toObservable(EventPreferenceChange::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ scheduleUpdateGUI("EventPreferenceChange") }, fabricPrivacy::logException)
|
.subscribe({ scheduleUpdateGUI() }, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventNewOpenLoopNotification::class.java)
|
.toObservable(EventNewOpenLoopNotification::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ scheduleUpdateGUI("EventNewOpenLoopNotification") }, fabricPrivacy::logException)
|
.subscribe({ scheduleUpdateGUI() }, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventPumpStatusChanged::class.java)
|
.toObservable(EventPumpStatusChanged::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
.delay(30, TimeUnit.MILLISECONDS, aapsSchedulers.main)
|
.delay(30, TimeUnit.MILLISECONDS, aapsSchedulers.main)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
overviewData.pumpStatus = it.getStatus(rh)
|
overviewData.pumpStatus = it.getStatus(rh)
|
||||||
updatePumpStatus("EventPumpStatusChanged")
|
updatePumpStatus()
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventEffectiveProfileSwitchChanged::class.java)
|
||||||
|
.observeOn(aapsSchedulers.main)
|
||||||
|
.subscribe({ updateProfile() }, fabricPrivacy::logException)
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventTempTargetChange::class.java)
|
||||||
|
.observeOn(aapsSchedulers.main)
|
||||||
|
.subscribe({ updateTemporaryTarget() }, fabricPrivacy::logException)
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventExtendedBolusChange::class.java)
|
||||||
|
.observeOn(aapsSchedulers.main)
|
||||||
|
.subscribe({ updateExtendedBolus() }, fabricPrivacy::logException)
|
||||||
|
disposable += rxBus
|
||||||
|
.toObservable(EventTempBasalChange::class.java)
|
||||||
|
.observeOn(aapsSchedulers.main)
|
||||||
|
.subscribe({ updateTemporaryBasal() }, fabricPrivacy::logException)
|
||||||
|
|
||||||
refreshLoop = Runnable {
|
refreshLoop = Runnable {
|
||||||
overviewPlugin.refreshLoop("refreshLoop")
|
refreshAll()
|
||||||
handler.postDelayed(refreshLoop, 60 * 1000L)
|
handler.postDelayed(refreshLoop, 60 * 1000L)
|
||||||
}
|
}
|
||||||
handler.postDelayed(refreshLoop, 60 * 1000L)
|
handler.postDelayed(refreshLoop, 60 * 1000L)
|
||||||
|
|
||||||
updateTime("onResume")
|
refreshAll()
|
||||||
updateCalcProgress("onResume")
|
updatePumpStatus()
|
||||||
updateProfile("onResume")
|
updateCalcProgress()
|
||||||
updateTemporaryBasal("onResume")
|
}
|
||||||
updateExtendedBolus("onResume")
|
|
||||||
updateTemporaryTarget("onResume")
|
fun refreshAll() {
|
||||||
updateBg("onResume")
|
runOnUiThread {
|
||||||
updateIobCob("onResume")
|
_binding ?: return@runOnUiThread
|
||||||
updateSensitivity("onResume")
|
updateBg()
|
||||||
updateGraph("onResume")
|
updateTime()
|
||||||
updatePumpStatus("onResume")
|
updateProfile()
|
||||||
updateNotification("onResume")
|
updateTemporaryBasal()
|
||||||
|
updateExtendedBolus()
|
||||||
|
updateTemporaryTarget()
|
||||||
|
updateIobCob()
|
||||||
|
updateSensitivity()
|
||||||
|
updateGraph()
|
||||||
|
updateNotification()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
@ -415,14 +403,15 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
loop.invoke("Accept temp button", false)
|
loop.invoke("Accept temp button", false)
|
||||||
if (lastRun?.lastAPSRun != null && lastRun.constraintsProcessed?.isChangeRequested == true) {
|
if (lastRun?.lastAPSRun != null && lastRun.constraintsProcessed?.isChangeRequested == true) {
|
||||||
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable {
|
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.BOLUS, UIRunnable {
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.tempbasal_label), lastRun.constraintsProcessed?.toSpanned()
|
if (isAdded)
|
||||||
?: "".toSpanned(), {
|
OKDialog.showConfirmation(activity, rh.gs(R.string.tempbasal_label), lastRun.constraintsProcessed?.toSpanned()
|
||||||
uel.log(Action.ACCEPTS_TEMP_BASAL, Sources.Overview)
|
?: "".toSpanned(), {
|
||||||
(context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?)?.cancel(Constants.notificationID)
|
uel.log(Action.ACCEPTS_TEMP_BASAL, Sources.Overview)
|
||||||
rxBus.send(EventWearInitiateAction("cancelChangeRequest"))
|
(context?.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?)?.cancel(Constants.notificationID)
|
||||||
Thread { loop.acceptChangeRequest() }.run()
|
rxBus.send(EventWearInitiateAction("cancelChangeRequest"))
|
||||||
binding.buttonsLayout.acceptTempButton.visibility = View.GONE
|
Thread { loop.acceptChangeRequest() }.run()
|
||||||
})
|
binding.buttonsLayout.acceptTempButton.visibility = View.GONE
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -558,10 +547,18 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
binding.buttonsLayout.calibrationButton.visibility = (xDripIsBgSource && actualBG != null && sp.getBoolean(R.string.key_show_calibration_button, true)).toVisibility()
|
binding.buttonsLayout.calibrationButton.visibility = (xDripIsBgSource && actualBG != null && sp.getBoolean(R.string.key_show_calibration_button, true)).toVisibility()
|
||||||
if (dexcomIsSource) {
|
if (dexcomIsSource) {
|
||||||
binding.buttonsLayout.cgmButton.setCompoundDrawablesWithIntrinsicBounds(null, rh.gd(R.drawable.ic_byoda), null, null)
|
binding.buttonsLayout.cgmButton.setCompoundDrawablesWithIntrinsicBounds(null, rh.gd(R.drawable.ic_byoda), null, null)
|
||||||
binding.buttonsLayout.cgmButton.setTextColor(rh.gc(R.color.colorLightGray))
|
for (drawable in binding.buttonsLayout.cgmButton.compoundDrawables) {
|
||||||
|
drawable?.mutate()
|
||||||
|
drawable?.colorFilter = PorterDuffColorFilter(rh.gac(context, R.attr.cgmdexColor), PorterDuff.Mode.SRC_IN)
|
||||||
|
}
|
||||||
|
binding.buttonsLayout.cgmButton.setTextColor(rh.gac(context, R.attr.cgmdexColor))
|
||||||
} else if (xDripIsBgSource) {
|
} else if (xDripIsBgSource) {
|
||||||
binding.buttonsLayout.cgmButton.setCompoundDrawablesWithIntrinsicBounds(null, rh.gd(R.drawable.ic_xdrip), null, null)
|
binding.buttonsLayout.cgmButton.setCompoundDrawablesWithIntrinsicBounds(null, rh.gd(R.drawable.ic_xdrip), null, null)
|
||||||
binding.buttonsLayout.cgmButton.setTextColor(rh.gc(R.color.colorCalibrationButton))
|
for (drawable in binding.buttonsLayout.cgmButton.compoundDrawables) {
|
||||||
|
drawable?.mutate()
|
||||||
|
drawable?.colorFilter = PorterDuffColorFilter(rh.gac(context, R.attr.cgmxdripColor), PorterDuff.Mode.SRC_IN)
|
||||||
|
}
|
||||||
|
binding.buttonsLayout.cgmButton.setTextColor(rh.gac(context, R.attr.cgmxdripColor))
|
||||||
}
|
}
|
||||||
binding.buttonsLayout.cgmButton.visibility = (sp.getBoolean(R.string.key_show_cgm_button, false) && (xDripIsBgSource || dexcomIsSource)).toVisibility()
|
binding.buttonsLayout.cgmButton.visibility = (sp.getBoolean(R.string.key_show_cgm_button, false) && (xDripIsBgSource || dexcomIsSource)).toVisibility()
|
||||||
|
|
||||||
|
@ -573,7 +570,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
if (event.isEnabled && event.trigger.shouldRun())
|
if (event.isEnabled && event.trigger.shouldRun())
|
||||||
context?.let { context ->
|
context?.let { context ->
|
||||||
SingleClickButton(context).also {
|
SingleClickButton(context).also {
|
||||||
it.setTextColor(rh.gc(R.color.colorTreatmentButton))
|
it.setTextColor(rh.gac(context, R.attr.treatmentButton))
|
||||||
it.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10f)
|
it.setTextSize(TypedValue.COMPLEX_UNIT_SP, 10f)
|
||||||
it.layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 0.5f).also { l ->
|
it.layoutParams = LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 0.5f).also { l ->
|
||||||
l.setMargins(0, 0, rh.dpToPx(-4), 0)
|
l.setMargins(0, 0, rh.dpToPx(-4), 0)
|
||||||
|
@ -582,11 +579,7 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
it.text = event.title
|
it.text = event.title
|
||||||
|
|
||||||
it.setOnClickListener {
|
it.setOnClickListener {
|
||||||
OKDialog.showConfirmation(
|
OKDialog.showConfirmation(context, rh.gs(R.string.run_question, event.title), { handler.post { automationPlugin.processEvent(event) } })
|
||||||
context,
|
|
||||||
rh.gs(R.string.run_question, event.title),
|
|
||||||
{ handler.post { automationPlugin.processEvent(event) } }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
binding.buttonsLayout.userButtonsLayout.addView(it)
|
binding.buttonsLayout.userButtonsLayout.addView(it)
|
||||||
}
|
}
|
||||||
|
@ -721,12 +714,12 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
val graph = GraphView(context)
|
val graph = GraphView(context)
|
||||||
graph.layoutParams =
|
graph.layoutParams =
|
||||||
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, rh.dpToPx(skinProvider.activeSkin().secondaryGraphHeight)).also { it.setMargins(0, rh.dpToPx(15), 0, rh.dpToPx(10)) }
|
LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, rh.dpToPx(skinProvider.activeSkin().secondaryGraphHeight)).also { it.setMargins(0, rh.dpToPx(15), 0, rh.dpToPx(10)) }
|
||||||
graph.gridLabelRenderer?.gridColor = rh.gc(R.color.graphgrid)
|
graph.gridLabelRenderer?.gridColor = rh.gac(context, R.attr.graphgrid)
|
||||||
graph.gridLabelRenderer?.reloadStyles()
|
graph.gridLabelRenderer?.reloadStyles()
|
||||||
graph.gridLabelRenderer?.isHorizontalLabelsVisible = false
|
graph.gridLabelRenderer?.isHorizontalLabelsVisible = false
|
||||||
graph.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
graph.gridLabelRenderer?.labelVerticalWidth = axisWidth
|
||||||
graph.gridLabelRenderer?.numVerticalLabels = 3
|
graph.gridLabelRenderer?.numVerticalLabels = 3
|
||||||
graph.viewport.backgroundColor = Color.argb(20, 255, 255, 255) // 8% of gray
|
graph.viewport.backgroundColor = rh.gac(context, R.attr.viewPortbackgroundColor)
|
||||||
relativeLayout.addView(graph)
|
relativeLayout.addView(graph)
|
||||||
|
|
||||||
val label = TextView(context)
|
val label = TextView(context)
|
||||||
|
@ -745,11 +738,11 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
|
|
||||||
var task: Runnable? = null
|
var task: Runnable? = null
|
||||||
|
|
||||||
private fun scheduleUpdateGUI(from: String) {
|
private fun scheduleUpdateGUI() {
|
||||||
class UpdateRunnable : Runnable {
|
class UpdateRunnable : Runnable {
|
||||||
|
|
||||||
override fun run() {
|
override fun run() {
|
||||||
overviewPlugin.refreshLoop(from)
|
refreshAll()
|
||||||
task = null
|
task = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -759,20 +752,20 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
@Suppress("UNUSED_PARAMETER")
|
fun updateBg() {
|
||||||
fun updateBg(from: String) {
|
_binding ?: return
|
||||||
val units = profileFunction.getUnits()
|
val units = profileFunction.getUnits()
|
||||||
binding.infoLayout.bg.text = overviewData.lastBg?.valueToUnitsString(units)
|
binding.infoLayout.bg.text = overviewData.lastBg?.valueToUnitsString(units)
|
||||||
?: rh.gs(R.string.notavailable)
|
?: rh.gs(R.string.notavailable)
|
||||||
binding.infoLayout.bg.setTextColor(overviewData.lastBgColor)
|
binding.infoLayout.bg.setTextColor(overviewData.lastBgColor(context))
|
||||||
binding.infoLayout.arrow.setImageResource(trendCalculator.getTrendArrow(overviewData.lastBg).directionToIcon())
|
binding.infoLayout.arrow.setImageResource(trendCalculator.getTrendArrow(overviewData.lastBg).directionToIcon())
|
||||||
binding.infoLayout.arrow.setColorFilter(overviewData.lastBgColor)
|
binding.infoLayout.arrow.setColorFilter(overviewData.lastBgColor(context))
|
||||||
binding.infoLayout.arrow.contentDescription = overviewData.lastBgDescription + " " + rh.gs(R.string.and) + " " + trendCalculator.getTrendDescription(overviewData.lastBg)
|
binding.infoLayout.arrow.contentDescription = overviewData.lastBgDescription + " " + rh.gs(R.string.and) + " " + trendCalculator.getTrendDescription(overviewData.lastBg)
|
||||||
|
|
||||||
val glucoseStatus = glucoseStatusProvider.glucoseStatusData
|
val glucoseStatus = glucoseStatusProvider.glucoseStatusData
|
||||||
if (glucoseStatus != null) {
|
if (glucoseStatus != null) {
|
||||||
binding.infoLayout.deltaLarge.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
|
binding.infoLayout.deltaLarge.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
|
||||||
binding.infoLayout.deltaLarge.setTextColor(overviewData.lastBgColor)
|
binding.infoLayout.deltaLarge.setTextColor(overviewData.lastBgColor(context))
|
||||||
binding.infoLayout.delta.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
|
binding.infoLayout.delta.text = Profile.toSignedUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units)
|
||||||
binding.infoLayout.avgDelta.text = Profile.toSignedUnitsString(glucoseStatus.shortAvgDelta, glucoseStatus.shortAvgDelta * Constants.MGDL_TO_MMOLL, units)
|
binding.infoLayout.avgDelta.text = Profile.toSignedUnitsString(glucoseStatus.shortAvgDelta, glucoseStatus.shortAvgDelta * Constants.MGDL_TO_MMOLL, units)
|
||||||
binding.infoLayout.longAvgDelta.text = Profile.toSignedUnitsString(glucoseStatus.longAvgDelta, glucoseStatus.longAvgDelta * Constants.MGDL_TO_MMOLL, units)
|
binding.infoLayout.longAvgDelta.text = Profile.toSignedUnitsString(glucoseStatus.longAvgDelta, glucoseStatus.longAvgDelta * Constants.MGDL_TO_MMOLL, units)
|
||||||
|
@ -809,70 +802,76 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
fun updateProfile() {
|
||||||
fun updateProfile(from: String) {
|
_binding ?: return
|
||||||
val profileBackgroundColor =
|
val profileBackgroundColor =
|
||||||
profileFunction.getProfile()?.let {
|
profileFunction.getProfile()?.let {
|
||||||
if (it is ProfileSealed.EPS) {
|
if (it is ProfileSealed.EPS) {
|
||||||
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
|
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
|
||||||
rh.gc(R.color.ribbonWarning)
|
rh.gac(context, R.attr.ribbonWarningColor)
|
||||||
else rh.gc(R.color.ribbonDefault)
|
else rh.gac(context, R.attr.ribbonDefaultColor)
|
||||||
} else if (it is ProfileSealed.PS) {
|
} else if (it is ProfileSealed.PS) {
|
||||||
rh.gc(R.color.ribbonDefault)
|
rh.gac(context, R.attr.ribbonDefaultColor)
|
||||||
} else {
|
} else {
|
||||||
rh.gc(R.color.ribbonDefault)
|
rh.gac(context, R.attr.ribbonDefaultColor)
|
||||||
}
|
}
|
||||||
} ?: rh.gc(R.color.ribbonCritical)
|
} ?: rh.gac(context, R.attr.ribbonCriticalColor)
|
||||||
|
|
||||||
val profileTextColor =
|
val profileTextColor =
|
||||||
profileFunction.getProfile()?.let {
|
profileFunction.getProfile()?.let {
|
||||||
if (it is ProfileSealed.EPS) {
|
if (it is ProfileSealed.EPS) {
|
||||||
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
|
if (it.value.originalPercentage != 100 || it.value.originalTimeshift != 0L || it.value.originalDuration != 0L)
|
||||||
rh.gc(R.color.ribbonTextWarning)
|
rh.gac(context, R.attr.ribbonTextWarningColor)
|
||||||
else rh.gc(R.color.ribbonTextDefault)
|
else rh.gac(context, R.attr.ribbonTextDefaultColor)
|
||||||
} else if (it is ProfileSealed.PS) {
|
} else if (it is ProfileSealed.PS) {
|
||||||
rh.gc(R.color.ribbonTextDefault)
|
rh.gac(context, R.attr.ribbonTextDefaultColor)
|
||||||
} else {
|
} else {
|
||||||
rh.gc(R.color.ribbonTextDefault)
|
rh.gac(context, R.attr.ribbonTextDefaultColor)
|
||||||
}
|
}
|
||||||
} ?: rh.gc(R.color.ribbonTextDefault)
|
} ?: rh.gac(context, R.attr.ribbonTextDefaultColor)
|
||||||
|
|
||||||
binding.activeProfile.text = profileFunction.getProfileNameWithRemainingTime()
|
binding.activeProfile.text = profileFunction.getProfileNameWithRemainingTime()
|
||||||
binding.activeProfile.setBackgroundColor(profileBackgroundColor)
|
binding.activeProfile.setBackgroundColor(profileBackgroundColor)
|
||||||
binding.activeProfile.setTextColor(profileTextColor)
|
binding.activeProfile.setTextColor(profileTextColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
private fun updateTemporaryBasal() {
|
||||||
fun updateTemporaryBasal(from: String) {
|
_binding ?: return
|
||||||
binding.infoLayout.baseBasal.text = overviewData.temporaryBasalText
|
binding.infoLayout.baseBasal.text = overviewData.temporaryBasalText(iobCobCalculator)
|
||||||
binding.infoLayout.baseBasal.setTextColor(overviewData.temporaryBasalColor)
|
binding.infoLayout.baseBasal.setTextColor(overviewData.temporaryBasalColor(context, iobCobCalculator))
|
||||||
binding.infoLayout.baseBasalIcon.setImageResource(overviewData.temporaryBasalIcon)
|
binding.infoLayout.baseBasalIcon.setImageResource(overviewData.temporaryBasalIcon(iobCobCalculator))
|
||||||
binding.infoLayout.basalLayout.setOnClickListener {
|
binding.infoLayout.basalLayout.setOnClickListener {
|
||||||
activity?.let { OKDialog.show(it, rh.gs(R.string.basal), overviewData.temporaryBasalDialogText) }
|
activity?.let { OKDialog.show(it, rh.gs(R.string.basal), overviewData.temporaryBasalDialogText(iobCobCalculator)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
private fun updateExtendedBolus() {
|
||||||
fun updateExtendedBolus(from: String) {
|
_binding ?: return
|
||||||
val pump = activePlugin.activePump
|
val pump = activePlugin.activePump
|
||||||
binding.infoLayout.extendedBolus.text = overviewData.extendedBolusText
|
binding.infoLayout.extendedBolus.text = overviewData.extendedBolusText(iobCobCalculator)
|
||||||
binding.infoLayout.extendedLayout.setOnClickListener {
|
binding.infoLayout.extendedLayout.setOnClickListener {
|
||||||
activity?.let { OKDialog.show(it, rh.gs(R.string.extended_bolus), overviewData.extendedBolusDialogText) }
|
activity?.let { OKDialog.show(it, rh.gs(R.string.extended_bolus), overviewData.extendedBolusDialogText(iobCobCalculator)) }
|
||||||
}
|
}
|
||||||
binding.infoLayout.extendedLayout.visibility = (iobCobCalculator.getExtendedBolus(dateUtil.now()) != null && !pump.isFakingTempsByExtendedBoluses).toVisibility()
|
binding.infoLayout.extendedLayout.visibility = (iobCobCalculator.getExtendedBolus(dateUtil.now()) != null && !pump.isFakingTempsByExtendedBoluses).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
fun updateTime() {
|
||||||
fun updateTime(from: String) {
|
_binding ?: return
|
||||||
binding.infoLayout.time.text = dateUtil.timeString(dateUtil.now())
|
binding.infoLayout.time.text = dateUtil.timeString(dateUtil.now())
|
||||||
// Status lights
|
// Status lights
|
||||||
val isPatchPump = activePlugin.activePump.pumpDescription.isPatchPump
|
val pump = activePlugin.activePump
|
||||||
|
val isPatchPump = pump.pumpDescription.isPatchPump
|
||||||
binding.statusLightsLayout.apply {
|
binding.statusLightsLayout.apply {
|
||||||
cannulaOrPatch.setImageResource(if (isPatchPump) R.drawable.ic_patch_pump_outline else R.drawable.ic_cp_age_cannula)
|
cannulaOrPatch.setImageResource(if (isPatchPump) R.drawable.ic_patch_pump_outline else R.drawable.ic_cp_age_cannula)
|
||||||
cannulaOrPatch.contentDescription = rh.gs(if (isPatchPump) R.string.statuslights_patch_pump_age else R.string.statuslights_cannula_age)
|
cannulaOrPatch.contentDescription = rh.gs(if (isPatchPump) R.string.statuslights_patch_pump_age else R.string.statuslights_cannula_age)
|
||||||
cannulaOrPatch.scaleX = if (isPatchPump) 1.4f else 2f
|
cannulaOrPatch.scaleX = if (isPatchPump) 1.4f else 2f
|
||||||
cannulaOrPatch.scaleY = cannulaOrPatch.scaleX
|
cannulaOrPatch.scaleY = cannulaOrPatch.scaleX
|
||||||
insulinAge.visibility = isPatchPump.not().toVisibility()
|
insulinAge.visibility = isPatchPump.not().toVisibility()
|
||||||
|
batteryLayout.visibility = (!isPatchPump || pump.pumpDescription.useHardwareLink).toVisibility()
|
||||||
|
pbAge.visibility = (pump.pumpDescription.isBatteryReplaceable || pump.isBatteryChangeLoggingEnabled()).toVisibility()
|
||||||
|
val useBatteryLevel = (pump.model() == PumpType.OMNIPOD_EROS && pump is OmnipodErosPumpPlugin)
|
||||||
|
|| (pump.model() != PumpType.ACCU_CHEK_COMBO && pump.model() != PumpType.OMNIPOD_DASH)
|
||||||
|
batteryLevel.visibility = useBatteryLevel.toVisibility()
|
||||||
statusLights.visibility = (sp.getBoolean(R.string.key_show_statuslights, true) || config.NSCLIENT).toVisibility()
|
statusLights.visibility = (sp.getBoolean(R.string.key_show_statuslights, true) || config.NSCLIENT).toVisibility()
|
||||||
}
|
}
|
||||||
statusLightHandler.updateStatusLights(
|
statusLightHandler.updateStatusLights(
|
||||||
|
@ -888,14 +887,14 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
processAps()
|
processAps()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
fun updateIobCob() {
|
||||||
fun updateIobCob(from: String) {
|
_binding ?: return
|
||||||
binding.infoLayout.iob.text = overviewData.iobText
|
binding.infoLayout.iob.text = overviewData.iobText(iobCobCalculator)
|
||||||
binding.infoLayout.iobLayout.setOnClickListener {
|
binding.infoLayout.iobLayout.setOnClickListener {
|
||||||
activity?.let { OKDialog.show(it, rh.gs(R.string.iob), overviewData.iobDialogText) }
|
activity?.let { OKDialog.show(it, rh.gs(R.string.iob), overviewData.iobDialogText(iobCobCalculator)) }
|
||||||
}
|
}
|
||||||
// cob
|
// cob
|
||||||
var cobText = overviewData.cobInfo?.displayText(rh, dateUtil, buildHelper.isEngineeringMode()) ?: rh.gs(R.string.value_unavailable_short)
|
var cobText = overviewData.cobInfo(iobCobCalculator).displayText(rh, dateUtil, buildHelper.isEngineeringMode()) ?: rh.gs(R.string.value_unavailable_short)
|
||||||
|
|
||||||
val constraintsProcessed = loop.lastRun?.constraintsProcessed
|
val constraintsProcessed = loop.lastRun?.constraintsProcessed
|
||||||
val lastRun = loop.lastRun
|
val lastRun = loop.lastRun
|
||||||
|
@ -916,14 +915,13 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
@Suppress("UNUSED_PARAMETER")
|
fun updateTemporaryTarget() {
|
||||||
fun updateTemporaryTarget(from: String) {
|
_binding ?: return
|
||||||
val units = profileFunction.getUnits()
|
val units = profileFunction.getUnits()
|
||||||
if (overviewData.temporaryTarget?.isInProgress(dateUtil) == false) overviewData.temporaryTarget = null
|
|
||||||
val tempTarget = overviewData.temporaryTarget
|
val tempTarget = overviewData.temporaryTarget
|
||||||
if (tempTarget != null) {
|
if (tempTarget != null) {
|
||||||
binding.tempTarget.setTextColor(rh.gc(R.color.ribbonTextWarning))
|
binding.tempTarget.setTextColor(rh.gac(context, R.attr.ribbonTextWarningColor))
|
||||||
binding.tempTarget.setBackgroundColor(rh.gc(R.color.ribbonWarning))
|
binding.tempTarget.setBackgroundColor(rh.gac(context, R.attr.ribbonWarningColor))
|
||||||
binding.tempTarget.text = Profile.toTargetRangeString(tempTarget.lowTarget, tempTarget.highTarget, GlucoseUnit.MGDL, units) + " " + dateUtil.untilString(tempTarget.end, rh)
|
binding.tempTarget.text = Profile.toTargetRangeString(tempTarget.lowTarget, tempTarget.highTarget, GlucoseUnit.MGDL, units) + " " + dateUtil.untilString(tempTarget.end, rh)
|
||||||
} else {
|
} else {
|
||||||
// If the target is not the same as set in the profile then oref has overridden it
|
// If the target is not the same as set in the profile then oref has overridden it
|
||||||
|
@ -933,19 +931,19 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
if (targetUsed != 0.0 && abs(profile.getTargetMgdl() - targetUsed) > 0.01) {
|
if (targetUsed != 0.0 && abs(profile.getTargetMgdl() - targetUsed) > 0.01) {
|
||||||
aapsLogger.debug("Adjusted target. Profile: ${profile.getTargetMgdl()} APS: $targetUsed")
|
aapsLogger.debug("Adjusted target. Profile: ${profile.getTargetMgdl()} APS: $targetUsed")
|
||||||
binding.tempTarget.text = Profile.toTargetRangeString(targetUsed, targetUsed, GlucoseUnit.MGDL, units)
|
binding.tempTarget.text = Profile.toTargetRangeString(targetUsed, targetUsed, GlucoseUnit.MGDL, units)
|
||||||
binding.tempTarget.setTextColor(rh.gc(R.color.ribbonTextWarning))
|
binding.tempTarget.setTextColor(rh.gac(context, R.attr.ribbonTextWarningColor))
|
||||||
binding.tempTarget.setBackgroundColor(rh.gc(R.color.tempTargetBackground))
|
binding.tempTarget.setBackgroundColor(rh.gac(context, R.attr.tempTargetBackgroundColor))
|
||||||
} else {
|
} else {
|
||||||
binding.tempTarget.setTextColor(rh.gc(R.color.ribbonTextDefault))
|
binding.tempTarget.setTextColor(rh.gac(context, R.attr.ribbonTextDefaultColor))
|
||||||
binding.tempTarget.setBackgroundColor(rh.gc(R.color.ribbonDefault))
|
binding.tempTarget.setBackgroundColor(rh.gac(context, R.attr.ribbonDefaultColor))
|
||||||
binding.tempTarget.text = Profile.toTargetRangeString(profile.getTargetLowMgdl(), profile.getTargetHighMgdl(), GlucoseUnit.MGDL, units)
|
binding.tempTarget.text = Profile.toTargetRangeString(profile.getTargetLowMgdl(), profile.getTargetHighMgdl(), GlucoseUnit.MGDL, units)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
private fun updateGraph() {
|
||||||
fun updateGraph(from: String) {
|
_binding ?: return
|
||||||
val pump = activePlugin.activePump
|
val pump = activePlugin.activePump
|
||||||
val graphData = GraphData(injector, binding.graphsLayout.bgGraph, overviewData)
|
val graphData = GraphData(injector, binding.graphsLayout.bgGraph, overviewData)
|
||||||
val menuChartSettings = overviewMenus.setting
|
val menuChartSettings = overviewMenus.setting
|
||||||
|
@ -953,6 +951,8 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
graphData.addBgReadings(menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal])
|
graphData.addBgReadings(menuChartSettings[0][OverviewMenus.CharType.PRE.ordinal])
|
||||||
if (buildHelper.isDev()) graphData.addBucketedData()
|
if (buildHelper.isDev()) graphData.addBucketedData()
|
||||||
graphData.addTreatments()
|
graphData.addTreatments()
|
||||||
|
if (menuChartSettings[0][OverviewMenus.CharType.TREAT.ordinal])
|
||||||
|
graphData.addTherapyEvents()
|
||||||
if (menuChartSettings[0][OverviewMenus.CharType.ACT.ordinal])
|
if (menuChartSettings[0][OverviewMenus.CharType.ACT.ordinal])
|
||||||
graphData.addActivity(0.8)
|
graphData.addActivity(0.8)
|
||||||
if ((pump.pumpDescription.isTempBasalCapable || config.NSCLIENT) && menuChartSettings[0][OverviewMenus.CharType.BAS.ordinal])
|
if ((pump.pumpDescription.isTempBasalCapable || config.NSCLIENT) && menuChartSettings[0][OverviewMenus.CharType.BAS.ordinal])
|
||||||
|
@ -1023,13 +1023,14 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
private fun updateCalcProgress() {
|
||||||
fun updateCalcProgress(from: String) {
|
_binding ?: return
|
||||||
binding.graphsLayout.iobCalculationProgress.text = overviewData.calcProgress
|
binding.progressBar.progress = overviewData.calcProgressPct
|
||||||
|
binding.progressBar.visibility = (overviewData.calcProgressPct != 100).toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
private fun updateSensitivity() {
|
||||||
fun updateSensitivity(from: String) {
|
_binding ?: return
|
||||||
if (sp.getBoolean(R.string.key_openapsama_useautosens, false) && constraintChecker.isAutosensModeEnabled().value()) {
|
if (sp.getBoolean(R.string.key_openapsama_useautosens, false) && constraintChecker.isAutosensModeEnabled().value()) {
|
||||||
binding.infoLayout.sensitivityIcon.setImageResource(R.drawable.ic_swap_vert_black_48dp_green)
|
binding.infoLayout.sensitivityIcon.setImageResource(R.drawable.ic_swap_vert_black_48dp_green)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1037,20 +1038,20 @@ class OverviewFragment : DaggerFragment(), View.OnClickListener, OnLongClickList
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.infoLayout.sensitivity.text =
|
binding.infoLayout.sensitivity.text =
|
||||||
overviewData.lastAutosensData?.let { autosensData ->
|
overviewData.lastAutosensData(iobCobCalculator)?.let { autosensData ->
|
||||||
String.format(Locale.ENGLISH, "%.0f%%", autosensData.autosensResult.ratio * 100)
|
String.format(Locale.ENGLISH, "%.0f%%", autosensData.autosensResult.ratio * 100)
|
||||||
} ?: ""
|
} ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
private fun updatePumpStatus() {
|
||||||
fun updatePumpStatus(from: String) {
|
_binding ?: return
|
||||||
val status = overviewData.pumpStatus
|
val status = overviewData.pumpStatus
|
||||||
binding.pumpStatus.text = status
|
binding.pumpStatus.text = status
|
||||||
binding.pumpStatusLayout.visibility = (status != "").toVisibility()
|
binding.pumpStatusLayout.visibility = (status != "").toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
private fun updateNotification() {
|
||||||
fun updateNotification(from: String) {
|
_binding ?: return
|
||||||
binding.notifications.let { notificationStore.updateNotifications(it) }
|
binding.notifications.let { notificationStore.updateNotifications(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview
|
package info.nightscout.androidaps.plugins.general.overview
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
|
import android.text.style.BackgroundColorSpan
|
||||||
import android.text.style.ForegroundColorSpan
|
import android.text.style.ForegroundColorSpan
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageButton
|
import android.widget.ImageButton
|
||||||
|
import androidx.annotation.AttrRes
|
||||||
import androidx.annotation.ColorRes
|
import androidx.annotation.ColorRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
|
@ -31,18 +34,18 @@ class OverviewMenus @Inject constructor(
|
||||||
private val loop: Loop,
|
private val loop: Loop,
|
||||||
private val config: Config
|
private val config: Config
|
||||||
) {
|
) {
|
||||||
|
enum class CharType(@StringRes val nameId: Int, @AttrRes val attrId: Int, @AttrRes val attrTextId: Int, val primary: Boolean, val secondary: Boolean, @StringRes val shortnameId: Int) {
|
||||||
enum class CharType(@StringRes val nameId: Int, @ColorRes val colorId: Int, val primary: Boolean, val secondary: Boolean, @StringRes val shortnameId: Int) {
|
PRE(R.string.overview_show_predictions, R.attr.predictionColor, R.attr.menuTextColor, primary = true, secondary = false, shortnameId = R.string.prediction_shortname),
|
||||||
PRE(R.string.overview_show_predictions, R.color.prediction, primary = true, secondary = false, shortnameId = R.string.prediction_shortname),
|
TREAT(R.string.overview_show_treatments, R.attr.predictionColor, R.attr.menuTextColor, primary = true, secondary = false, shortnameId = R.string.treatments_shortname),
|
||||||
BAS(R.string.overview_show_basals, R.color.basal, primary = true, secondary = false, shortnameId = R.string.basal_shortname),
|
BAS(R.string.overview_show_basals, R.attr.basal, R.attr.menuTextColor, primary = true, secondary = false,shortnameId = R.string.basal_shortname),
|
||||||
ABS(R.string.overview_show_absinsulin, R.color.iob, primary = false, secondary = true, shortnameId = R.string.abs_insulin_shortname),
|
ABS(R.string.overview_show_absinsulin, R.attr.iobColor, R.attr.menuTextColor, primary = false, secondary = true,shortnameId = R.string.abs_insulin_shortname),
|
||||||
IOB(R.string.overview_show_iob, R.color.iob, primary = false, secondary = true, shortnameId = R.string.iob),
|
IOB(R.string.overview_show_iob, R.attr.iobColor, R.attr.menuTextColor, primary = false, secondary = true,shortnameId = R.string.iob),
|
||||||
COB(R.string.overview_show_cob, R.color.cob, primary = false, secondary = true, shortnameId = R.string.cob),
|
COB(R.string.overview_show_cob, R.attr.cobColor, R.attr.menuTextColor, primary = false, secondary = true,shortnameId = R.string.cob),
|
||||||
DEV(R.string.overview_show_deviations, R.color.bgi, primary = false, secondary = true, shortnameId = R.string.deviation_shortname),
|
DEV(R.string.overview_show_deviations, R.attr.bgiColor, R.attr.menuTextColor, primary = false, secondary = true,shortnameId = R.string.deviation_shortname),
|
||||||
BGI(R.string.overview_show_bgi, R.color.bgi, primary = false, secondary = true, shortnameId = R.string.bgi_shortname),
|
BGI(R.string.overview_show_bgi, R.attr.bgiColor, R.attr.menuTextColor, primary = false, secondary = true,shortnameId = R.string.bgi_shortname),
|
||||||
SEN(R.string.overview_show_sensitivity, R.color.ratio, primary = false, secondary = true, shortnameId = R.string.sensitivity_shortname),
|
SEN(R.string.overview_show_sensitivity, R.attr.ratioColor, R.attr.menuTextColorInverse, primary = false, secondary = true,shortnameId = R.string.sensitivity_shortname),
|
||||||
ACT(R.string.overview_show_activity, R.color.activity, primary = true, secondary = false, shortnameId = R.string.activity_shortname),
|
ACT(R.string.overview_show_activity, R.attr.activityColor, R.attr.menuTextColor, primary = true, secondary = false,shortnameId = R.string.activity_shortname),
|
||||||
DEVSLOPE(R.string.overview_show_deviationslope, R.color.devslopepos, primary = false, secondary = true, shortnameId = R.string.devslope_shortname)
|
DEVSLOPE(R.string.overview_show_deviationslope, R.attr.devslopeposColor, R.attr.menuTextColor, primary = false, secondary = true,shortnameId = R.string.devslope_shortname)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -86,7 +89,7 @@ class OverviewMenus @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setupChartMenu(chartButton: ImageButton) {
|
fun setupChartMenu(context: Context, chartButton: ImageButton) {
|
||||||
val settingsCopy = setting
|
val settingsCopy = setting
|
||||||
val numOfGraphs = settingsCopy.size // 1 main + x secondary
|
val numOfGraphs = settingsCopy.size // 1 main + x secondary
|
||||||
|
|
||||||
|
@ -119,8 +122,9 @@ class OverviewMenus @Inject constructor(
|
||||||
if (insert) {
|
if (insert) {
|
||||||
val item = popup.menu.add(Menu.NONE, m.ordinal + 100 * (g + 1), Menu.NONE, rh.gs(m.nameId))
|
val item = popup.menu.add(Menu.NONE, m.ordinal + 100 * (g + 1), Menu.NONE, rh.gs(m.nameId))
|
||||||
val title = item.title
|
val title = item.title
|
||||||
val s = SpannableString(title)
|
val s = SpannableString(" " + title + " ")
|
||||||
s.setSpan(ForegroundColorSpan(rh.gc(m.colorId)), 0, s.length, 0)
|
s.setSpan(ForegroundColorSpan(rh.gac(context, m.attrTextId)), 0, s.length, 0)
|
||||||
|
s.setSpan(BackgroundColorSpan(rh.gac(context, m.attrId)), 0, s.length, 0)
|
||||||
item.title = s
|
item.title = s
|
||||||
item.isCheckable = true
|
item.isCheckable = true
|
||||||
item.isChecked = settingsCopy[g][m.ordinal]
|
item.isChecked = settingsCopy[g][m.ordinal]
|
||||||
|
@ -152,7 +156,7 @@ class OverviewMenus @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
storeGraphConfig()
|
storeGraphConfig()
|
||||||
setupChartMenu(chartButton)
|
setupChartMenu(context, chartButton)
|
||||||
rxBus.send(EventRefreshOverview("OnMenuItemClickListener", now = true))
|
rxBus.send(EventRefreshOverview("OnMenuItemClickListener", now = true))
|
||||||
return@setOnMenuItemClickListener true
|
return@setOnMenuItemClickListener true
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,25 +4,26 @@ import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.preference.SwitchPreference
|
import androidx.preference.SwitchPreference
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.database.AppRepository
|
import info.nightscout.androidaps.events.EventPumpStatusChanged
|
||||||
import info.nightscout.androidaps.database.ValueWrapper
|
|
||||||
import info.nightscout.androidaps.events.*
|
|
||||||
import info.nightscout.androidaps.extensions.*
|
import info.nightscout.androidaps.extensions.*
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.Config
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
import info.nightscout.androidaps.interfaces.Overview
|
||||||
import info.nightscout.shared.logging.LTag
|
import info.nightscout.androidaps.interfaces.PluginBase
|
||||||
import info.nightscout.androidaps.plugins.aps.events.EventLoopInvoked
|
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginType
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.*
|
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.events.EventUpdateOverviewCalcProgress
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.events.EventUpdateOverviewNotification
|
||||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.Scale
|
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.Scale
|
||||||
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.ScaledDataPoint
|
import info.nightscout.androidaps.plugins.general.overview.graphExtensions.ScaledDataPoint
|
||||||
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
|
import info.nightscout.androidaps.plugins.general.overview.notifications.NotificationStore
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventBucketedDataCreated
|
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
@ -41,9 +42,6 @@ class OverviewPlugin @Inject constructor(
|
||||||
private val aapsSchedulers: AapsSchedulers,
|
private val aapsSchedulers: AapsSchedulers,
|
||||||
rh: ResourceHelper,
|
rh: ResourceHelper,
|
||||||
private val config: Config,
|
private val config: Config,
|
||||||
private val dateUtil: DateUtil,
|
|
||||||
private val iobCobCalculator: IobCobCalculator,
|
|
||||||
private val repository: AppRepository,
|
|
||||||
private val overviewData: OverviewData,
|
private val overviewData: OverviewData,
|
||||||
private val overviewMenus: OverviewMenus
|
private val overviewMenus: OverviewMenus
|
||||||
) : PluginBase(
|
) : PluginBase(
|
||||||
|
@ -89,62 +87,9 @@ class OverviewPlugin @Inject constructor(
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventIobCalculationProgress::class.java)
|
.toObservable(EventIobCalculationProgress::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ overviewData.calcProgress = it.progress; overviewBus.send(EventUpdateOverviewCalcProgress("EventIobCalculationProgress")) }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventTempBasalChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ overviewBus.send(EventUpdateOverviewTemporaryBasal("EventTempBasalChange")) }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventExtendedBolusChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ overviewBus.send(EventUpdateOverviewExtendedBolus("EventExtendedBolusChange")) }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventNewBG::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ loadBg("EventNewBG") }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventTempTargetChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ loadTemporaryTarget("EventTempTargetChange") }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventTreatmentChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({
|
.subscribe({
|
||||||
loadIobCobResults("EventTreatmentChange")
|
overviewData.calcProgressPct = it.pass.finalPercent(it.progressPct)
|
||||||
overviewData.prepareTreatmentsData("EventTreatmentChange")
|
overviewBus.send(EventUpdateOverviewCalcProgress("EventIobCalculationProgress"))
|
||||||
overviewBus.send(EventUpdateOverviewGraph("EventTreatmentChange"))
|
|
||||||
}, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventTherapyEventChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({
|
|
||||||
overviewData.prepareTreatmentsData("EventTherapyEventChange")
|
|
||||||
overviewBus.send(EventUpdateOverviewGraph("EventTherapyEventChange"))
|
|
||||||
}, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventBucketedDataCreated::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({
|
|
||||||
overviewData.prepareBucketedData("EventBucketedDataCreated")
|
|
||||||
overviewData.prepareBgData("EventBucketedDataCreated")
|
|
||||||
overviewBus.send(EventUpdateOverviewGraph("EventBucketedDataCreated"))
|
|
||||||
}, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventLoopInvoked::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ overviewData.preparePredictions("EventLoopInvoked") }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventEffectiveProfileSwitchChanged::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({
|
|
||||||
loadProfile("EventEffectiveProfileSwitchChanged")
|
|
||||||
overviewData.prepareBasalData("EventEffectiveProfileSwitchChanged")
|
|
||||||
}, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({
|
|
||||||
if (it.cause !is EventCustomCalculationFinished) refreshLoop("EventAutosensCalculationFinished")
|
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventPumpStatusChanged::class.java)
|
.toObservable(EventPumpStatusChanged::class.java)
|
||||||
|
@ -152,20 +97,7 @@ class OverviewPlugin @Inject constructor(
|
||||||
.subscribe({
|
.subscribe({
|
||||||
overviewData.pumpStatus = it.getStatus(rh)
|
overviewData.pumpStatus = it.getStatus(rh)
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventPreferenceChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ event ->
|
|
||||||
if (event.isChanged(rh, R.string.key_units)) {
|
|
||||||
overviewData.reset()
|
|
||||||
overviewData.prepareBucketedData("EventBucketedDataCreated")
|
|
||||||
overviewData.prepareBgData("EventBucketedDataCreated")
|
|
||||||
overviewBus.send(EventUpdateOverviewGraph("EventBucketedDataCreated"))
|
|
||||||
loadAll("EventPreferenceChange")
|
|
||||||
}
|
|
||||||
}, fabricPrivacy::logException)
|
|
||||||
|
|
||||||
Thread { loadAll("onResume") }.start()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop() {
|
override fun onStop() {
|
||||||
|
@ -243,7 +175,7 @@ class OverviewPlugin @Inject constructor(
|
||||||
.storeDouble(R.string.key_statuslights_bat_critical, sp, rh)
|
.storeDouble(R.string.key_statuslights_bat_critical, sp, rh)
|
||||||
.storeInt(R.string.key_boluswizard_percentage, sp, rh)
|
.storeInt(R.string.key_boluswizard_percentage, sp, rh)
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
@Volatile
|
@Volatile
|
||||||
var runningRefresh = false
|
var runningRefresh = false
|
||||||
override fun refreshLoop(from: String) {
|
override fun refreshLoop(from: String) {
|
||||||
|
@ -284,38 +216,5 @@ class OverviewPlugin @Inject constructor(
|
||||||
overviewBus.send(EventUpdateOverviewGraph(from))
|
overviewBus.send(EventUpdateOverviewGraph(from))
|
||||||
aapsLogger.debug(LTag.UI, "loadAll finished")
|
aapsLogger.debug(LTag.UI, "loadAll finished")
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
private fun loadProfile(from: String) {
|
|
||||||
overviewBus.send(EventUpdateOverviewProfile(from))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadTemporaryTarget(from: String) {
|
|
||||||
val tempTarget = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet()
|
|
||||||
if (tempTarget is ValueWrapper.Existing) overviewData.temporaryTarget = tempTarget.value
|
|
||||||
else overviewData.temporaryTarget = null
|
|
||||||
overviewBus.send(EventUpdateOverviewTemporaryTarget(from))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadAsData(from: String) {
|
|
||||||
overviewData.lastAutosensData = iobCobCalculator.ads.getLastAutosensData("Overview", aapsLogger, dateUtil)
|
|
||||||
overviewBus.send(EventUpdateOverviewSensitivity(from))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadBg(from: String) {
|
|
||||||
val gvWrapped = repository.getLastGlucoseValueWrapped().blockingGet()
|
|
||||||
if (gvWrapped is ValueWrapper.Existing) overviewData.lastBg = gvWrapped.value
|
|
||||||
else overviewData.lastBg = null
|
|
||||||
overviewBus.send(EventUpdateOverviewBg(from))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadIobCobResults(from: String) {
|
|
||||||
overviewData.bolusIob = iobCobCalculator.calculateIobFromBolus().round()
|
|
||||||
overviewData.basalIob = iobCobCalculator.calculateIobFromTempBasalsIncludingConvertedExtended().round()
|
|
||||||
overviewData.cobInfo = iobCobCalculator.getCobInfo(true, "Overview COB")
|
|
||||||
val lastCarbs = repository.getLastCarbsRecordWrapped().blockingGet()
|
|
||||||
overviewData.lastCarbsTime = if (lastCarbs is ValueWrapper.Existing) lastCarbs.value.timestamp else 0L
|
|
||||||
|
|
||||||
overviewBus.send(EventUpdateOverviewIobCob(from))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview
|
package info.nightscout.androidaps.plugins.general.overview
|
||||||
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.view.View
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
@ -42,7 +41,7 @@ class StatusLightHandler @Inject constructor(
|
||||||
handleAge(careportal_cannula_age, TherapyEvent.Type.CANNULA_CHANGE, R.string.key_statuslights_cage_warning, 48.0, R.string.key_statuslights_cage_critical, 72.0)
|
handleAge(careportal_cannula_age, TherapyEvent.Type.CANNULA_CHANGE, R.string.key_statuslights_cage_warning, 48.0, R.string.key_statuslights_cage_critical, 72.0)
|
||||||
handleAge(careportal_insulin_age, TherapyEvent.Type.INSULIN_CHANGE, R.string.key_statuslights_iage_warning, 72.0, R.string.key_statuslights_iage_critical, 144.0)
|
handleAge(careportal_insulin_age, TherapyEvent.Type.INSULIN_CHANGE, R.string.key_statuslights_iage_warning, 72.0, R.string.key_statuslights_iage_critical, 144.0)
|
||||||
handleAge(careportal_sensor_age, TherapyEvent.Type.SENSOR_CHANGE, R.string.key_statuslights_sage_warning, 216.0, R.string.key_statuslights_sage_critical, 240.0)
|
handleAge(careportal_sensor_age, TherapyEvent.Type.SENSOR_CHANGE, R.string.key_statuslights_sage_warning, 216.0, R.string.key_statuslights_sage_critical, 240.0)
|
||||||
if (pump.pumpDescription.isBatteryReplaceable || (pump is OmnipodErosPumpPlugin && pump.isUseRileyLinkBatteryLevel && pump.isBatteryChangeLoggingEnabled)) {
|
if (pump.pumpDescription.isBatteryReplaceable || pump.isBatteryChangeLoggingEnabled()) {
|
||||||
handleAge(careportal_pb_age, TherapyEvent.Type.PUMP_BATTERY_CHANGE, R.string.key_statuslights_bage_warning, 216.0, R.string.key_statuslights_bage_critical, 240.0)
|
handleAge(careportal_pb_age, TherapyEvent.Type.PUMP_BATTERY_CHANGE, R.string.key_statuslights_bage_warning, 216.0, R.string.key_statuslights_bage_critical, 240.0)
|
||||||
}
|
}
|
||||||
if (!config.NSCLIENT) {
|
if (!config.NSCLIENT) {
|
||||||
|
@ -58,16 +57,16 @@ class StatusLightHandler @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.NSCLIENT) {
|
if (!config.NSCLIENT) {
|
||||||
if (pump.model() == PumpType.OMNIPOD_DASH) {
|
// The Omnipod Eros does not report its battery level. However, some RileyLink alternatives do.
|
||||||
// Omnipod Dash does not report its battery level
|
// Depending on the user's configuration, we will either show the battery level reported by the RileyLink or "n/a"
|
||||||
careportal_battery_level?.text = rh.gs(R.string.notavailable)
|
// Pump instance check is needed because at startup, the pump can still be VirtualPumpPlugin and that will cause a crash
|
||||||
careportal_battery_level?.setTextColor(Color.WHITE)
|
val erosBatteryLinkAvailable = pump.model() == PumpType.OMNIPOD_EROS && pump is OmnipodErosPumpPlugin && pump.isUseRileyLinkBatteryLevel
|
||||||
} else if (pump.model() == PumpType.OMNIPOD_EROS && pump is OmnipodErosPumpPlugin) { // instance of check is needed because at startup, pump can still be VirtualPumpPlugin and that will cause a crash because of the class cast below
|
|
||||||
// The Omnipod Eros does not report its battery level. However, some RileyLink alternatives do.
|
if (pump.model().supportBatteryLevel || erosBatteryLinkAvailable) {
|
||||||
// Depending on the user's configuration, we will either show the battery level reported by the RileyLink or "n/a"
|
|
||||||
handleOmnipodErosBatteryLevel(careportal_battery_level, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%", pump.isUseRileyLinkBatteryLevel)
|
|
||||||
} else if (pump.model() != PumpType.ACCU_CHEK_COMBO) {
|
|
||||||
handleLevel(careportal_battery_level, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%")
|
handleLevel(careportal_battery_level, R.string.key_statuslights_bat_critical, 26.0, R.string.key_statuslights_bat_warning, 51.0, pump.batteryLevel.toDouble(), "%")
|
||||||
|
} else {
|
||||||
|
careportal_battery_level?.text = rh.gs(R.string.notavailable)
|
||||||
|
careportal_battery_level?.setTextColor(rh.gac(careportal_battery_level.context, R.attr.defaultTextColor))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,13 +103,4 @@ class StatusLightHandler @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("SameParameterValue")
|
|
||||||
private fun handleOmnipodErosBatteryLevel(view: TextView?, criticalSetting: Int, criticalDefaultValue: Double, warnSetting: Int, warnDefaultValue: Double, level: Double, units: String, useRileyLinkBatteryLevel: Boolean) {
|
|
||||||
if (useRileyLinkBatteryLevel) {
|
|
||||||
handleLevel(view, criticalSetting, criticalDefaultValue, warnSetting, warnDefaultValue, level, units)
|
|
||||||
} else {
|
|
||||||
view?.text = rh.gs(R.string.notavailable)
|
|
||||||
view?.setTextColor(Color.WHITE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -2,32 +2,28 @@ package info.nightscout.androidaps.plugins.general.overview.activities
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.SparseArray
|
||||||
import android.view.LayoutInflater
|
import android.view.*
|
||||||
import android.view.MenuItem
|
import androidx.core.util.forEach
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.Button
|
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper.ACTION_STATE_DRAG
|
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper.DOWN
|
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper.END
|
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper.START
|
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper.UP
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult
|
import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult
|
||||||
import info.nightscout.androidaps.databinding.OverviewQuickwizardlistActivityBinding
|
import info.nightscout.androidaps.databinding.OverviewQuickwizardlistActivityBinding
|
||||||
|
import info.nightscout.androidaps.databinding.OverviewQuickwizardlistItemBinding
|
||||||
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.utils.dragHelpers.ItemTouchHelperAdapter
|
||||||
|
import info.nightscout.androidaps.utils.dragHelpers.OnStartDragListener
|
||||||
|
import info.nightscout.androidaps.utils.dragHelpers.SimpleItemTouchHelperCallback
|
||||||
import info.nightscout.androidaps.plugins.general.overview.dialogs.EditQuickWizardDialog
|
import info.nightscout.androidaps.plugins.general.overview.dialogs.EditQuickWizardDialog
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventQuickWizardChange
|
import info.nightscout.androidaps.plugins.general.overview.events.EventQuickWizardChange
|
||||||
|
import info.nightscout.androidaps.utils.ActionModeHelper
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
import info.nightscout.androidaps.utils.wizard.QuickWizard
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
|
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry
|
||||||
|
@ -36,7 +32,7 @@ import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class QuickWizardListActivity : DaggerAppCompatActivityWithResult() {
|
class QuickWizardListActivity : DaggerAppCompatActivityWithResult(), OnStartDragListener {
|
||||||
|
|
||||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||||
@Inject lateinit var rxBus: RxBus
|
@Inject lateinit var rxBus: RxBus
|
||||||
|
@ -46,134 +42,78 @@ class QuickWizardListActivity : DaggerAppCompatActivityWithResult() {
|
||||||
@Inject lateinit var sp: SP
|
@Inject lateinit var sp: SP
|
||||||
|
|
||||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||||
|
private lateinit var actionHelper: ActionModeHelper<QuickWizardEntry>
|
||||||
|
private val itemTouchHelper = ItemTouchHelper(SimpleItemTouchHelperCallback())
|
||||||
private lateinit var binding: OverviewQuickwizardlistActivityBinding
|
private lateinit var binding: OverviewQuickwizardlistActivityBinding
|
||||||
|
|
||||||
private val itemTouchHelper by lazy {
|
override fun onStartDrag(viewHolder: RecyclerView.ViewHolder) {
|
||||||
val simpleItemTouchCallback = object : ItemTouchHelper.SimpleCallback(UP or DOWN or START or END, 0) {
|
|
||||||
|
|
||||||
override fun onMove(
|
|
||||||
recyclerView: RecyclerView,
|
|
||||||
viewHolder: RecyclerView.ViewHolder,
|
|
||||||
target: RecyclerView.ViewHolder
|
|
||||||
): Boolean {
|
|
||||||
val adapter = recyclerView.adapter as RecyclerViewAdapter
|
|
||||||
val from = viewHolder.layoutPosition
|
|
||||||
val to = target.layoutPosition
|
|
||||||
adapter.moveItem(from, to)
|
|
||||||
adapter.notifyItemMoved(from, to)
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
|
|
||||||
super.onSelectedChanged(viewHolder, actionState)
|
|
||||||
|
|
||||||
if (actionState == ACTION_STATE_DRAG) {
|
|
||||||
viewHolder?.itemView?.alpha = 0.5f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
|
|
||||||
super.clearView(recyclerView, viewHolder)
|
|
||||||
|
|
||||||
viewHolder.itemView.alpha = 1.0f
|
|
||||||
|
|
||||||
val adapter = recyclerView.adapter as RecyclerViewAdapter
|
|
||||||
adapter.onDrop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemTouchHelper(simpleItemTouchCallback)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun startDragging(viewHolder: RecyclerView.ViewHolder) {
|
|
||||||
itemTouchHelper.startDrag(viewHolder)
|
itemTouchHelper.startDrag(viewHolder)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inner class RecyclerViewAdapter(var fragmentManager: FragmentManager) : RecyclerView.Adapter<RecyclerViewAdapter.QuickWizardEntryViewHolder>() {
|
private inner class RecyclerViewAdapter(var fragmentManager: FragmentManager) : RecyclerView.Adapter<RecyclerViewAdapter.QuickWizardEntryViewHolder>(), ItemTouchHelperAdapter {
|
||||||
|
|
||||||
|
private inner class QuickWizardEntryViewHolder(val binding: OverviewQuickwizardlistItemBinding, val fragmentManager: FragmentManager) : RecyclerView.ViewHolder(binding.root)
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuickWizardEntryViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QuickWizardEntryViewHolder {
|
||||||
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.overview_quickwizardlist_item, parent, false)
|
val binding = OverviewQuickwizardlistItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
val viewHolder = QuickWizardEntryViewHolder(itemView, fragmentManager)
|
return QuickWizardEntryViewHolder(binding, fragmentManager)
|
||||||
|
|
||||||
viewHolder.handleView.setOnTouchListener { _, event ->
|
|
||||||
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
|
|
||||||
startDragging(viewHolder)
|
|
||||||
}
|
|
||||||
return@setOnTouchListener true
|
|
||||||
}
|
|
||||||
|
|
||||||
return viewHolder
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
override fun onBindViewHolder(holder: QuickWizardEntryViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: QuickWizardEntryViewHolder, position: Int) {
|
||||||
holder.from.text = dateUtil.timeString(quickWizard[position].validFromDate())
|
val entry = quickWizard[position]
|
||||||
holder.to.text = dateUtil.timeString(quickWizard[position].validToDate())
|
holder.binding.from.text = dateUtil.timeString(entry.validFromDate())
|
||||||
val wearControl = sp.getBoolean(R.string.key_wear_control, false)
|
holder.binding.to.text = dateUtil.timeString(entry.validToDate())
|
||||||
|
holder.binding.buttonText.text = entry.buttonText()
|
||||||
if (wearControl) {
|
holder.binding.carbs.text = rh.gs(R.string.format_carbs, entry.carbs())
|
||||||
holder.handleView.visibility = View.VISIBLE
|
if (entry.device() == QuickWizardEntry.DEVICE_ALL) {
|
||||||
|
holder.binding.device.visibility = View.GONE
|
||||||
} else {
|
} else {
|
||||||
holder.handleView.visibility = View.GONE
|
holder.binding.device.visibility = View.VISIBLE
|
||||||
}
|
holder.binding.device.setImageResource(
|
||||||
if (quickWizard[position].device() == QuickWizardEntry.DEVICE_ALL) {
|
|
||||||
holder.device.visibility = View.GONE
|
|
||||||
} else {
|
|
||||||
holder.device.visibility = View.VISIBLE
|
|
||||||
holder.device.setImageResource(
|
|
||||||
when (quickWizard[position].device()) {
|
when (quickWizard[position].device()) {
|
||||||
QuickWizardEntry.DEVICE_WATCH -> R.drawable.ic_watch
|
QuickWizardEntry.DEVICE_WATCH -> R.drawable.ic_watch
|
||||||
else -> R.drawable.ic_smartphone
|
else -> R.drawable.ic_smartphone
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
holder.buttonText.text = quickWizard[position].buttonText()
|
holder.binding.root.setOnClickListener {
|
||||||
holder.carbs.text = rh.gs(R.string.format_carbs, quickWizard[position].carbs())
|
if (actionHelper.isNoAction) {
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemCount(): Int = quickWizard.size()
|
|
||||||
|
|
||||||
private inner class QuickWizardEntryViewHolder(itemView: View, var fragmentManager: FragmentManager) : RecyclerView.ViewHolder(itemView) {
|
|
||||||
|
|
||||||
val buttonText: TextView = itemView.findViewById(R.id.overview_quickwizard_item_buttonText)
|
|
||||||
val carbs: TextView = itemView.findViewById(R.id.overview_quickwizard_item_carbs)
|
|
||||||
val from: TextView = itemView.findViewById(R.id.overview_quickwizard_item_from)
|
|
||||||
val handleView: ImageView = itemView.findViewById(R.id.handleView)
|
|
||||||
val device: ImageView = itemView.findViewById(R.id.overview_quickwizard_item_device)
|
|
||||||
val to: TextView = itemView.findViewById(R.id.overview_quickwizard_item_to)
|
|
||||||
private val editButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_edit_button)
|
|
||||||
private val removeButton: Button = itemView.findViewById(R.id.overview_quickwizard_item_remove_button)
|
|
||||||
|
|
||||||
init {
|
|
||||||
editButton.setOnClickListener {
|
|
||||||
val manager = fragmentManager
|
val manager = fragmentManager
|
||||||
val editQuickWizardDialog = EditQuickWizardDialog()
|
val editQuickWizardDialog = EditQuickWizardDialog()
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putInt("position", bindingAdapterPosition)
|
bundle.putInt("position", position)
|
||||||
editQuickWizardDialog.arguments = bundle
|
editQuickWizardDialog.arguments = bundle
|
||||||
editQuickWizardDialog.show(manager, "EditQuickWizardDialog")
|
editQuickWizardDialog.show(manager, "EditQuickWizardDialog")
|
||||||
}
|
} else if (actionHelper.isRemoving) {
|
||||||
removeButton.setOnClickListener {
|
holder.binding.cbRemove.toggle()
|
||||||
quickWizard.remove(bindingAdapterPosition)
|
actionHelper.updateSelection(position, entry, holder.binding.cbRemove.isChecked)
|
||||||
rxBus.send(EventQuickWizardChange())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
holder.binding.sortHandle.setOnTouchListener { _, event ->
|
||||||
|
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
|
||||||
|
onStartDrag(holder)
|
||||||
|
return@setOnTouchListener true
|
||||||
|
}
|
||||||
|
return@setOnTouchListener false
|
||||||
|
}
|
||||||
|
holder.binding.cbRemove.isChecked = actionHelper.isSelected(position)
|
||||||
|
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
||||||
|
actionHelper.updateSelection(position, entry, value)
|
||||||
|
}
|
||||||
|
holder.binding.sortHandle.visibility = actionHelper.isSorting.toVisibility()
|
||||||
|
holder.binding.cbRemove.visibility = actionHelper.isRemoving.toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun moveItem(from: Int, to: Int) {
|
override fun getItemCount() = quickWizard.size()
|
||||||
Log.i("QuickWizard", "moveItem")
|
|
||||||
quickWizard.move(from, to)
|
override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean {
|
||||||
|
binding.recyclerview.adapter?.notifyItemMoved(fromPosition, toPosition)
|
||||||
|
quickWizard.move(fromPosition, toPosition)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDrop() {
|
override fun onDrop() = rxBus.send(EventQuickWizardChange())
|
||||||
Log.i("QuickWizard", "onDrop")
|
|
||||||
rxBus.send(EventQuickWizardChange())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -181,6 +121,11 @@ class QuickWizardListActivity : DaggerAppCompatActivityWithResult() {
|
||||||
binding = OverviewQuickwizardlistActivityBinding.inflate(layoutInflater)
|
binding = OverviewQuickwizardlistActivityBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
actionHelper = ActionModeHelper(rh, this)
|
||||||
|
actionHelper.setUpdateListHandler { binding.recyclerview.adapter?.notifyDataSetChanged() }
|
||||||
|
actionHelper.setOnRemoveHandler { removeSelected(it) }
|
||||||
|
actionHelper.enableSort = true
|
||||||
|
|
||||||
title = rh.gs(R.string.quickwizard)
|
title = rh.gs(R.string.quickwizard)
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
|
@ -191,6 +136,7 @@ class QuickWizardListActivity : DaggerAppCompatActivityWithResult() {
|
||||||
itemTouchHelper.attachToRecyclerView(binding.recyclerview)
|
itemTouchHelper.attachToRecyclerView(binding.recyclerview)
|
||||||
|
|
||||||
binding.addButton.setOnClickListener {
|
binding.addButton.setOnClickListener {
|
||||||
|
actionHelper.finish()
|
||||||
val manager = supportFragmentManager
|
val manager = supportFragmentManager
|
||||||
val editQuickWizardDialog = EditQuickWizardDialog()
|
val editQuickWizardDialog = EditQuickWizardDialog()
|
||||||
editQuickWizardDialog.show(manager, "EditQuickWizardDialog")
|
editQuickWizardDialog.show(manager, "EditQuickWizardDialog")
|
||||||
|
@ -210,9 +156,25 @@ class QuickWizardListActivity : DaggerAppCompatActivityWithResult() {
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
|
actionHelper.finish()
|
||||||
super.onPause()
|
super.onPause()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun removeSelected(selectedItems: SparseArray<QuickWizardEntry>) {
|
||||||
|
OKDialog.showConfirmation(this, rh.gs(R.string.removerecord), getConfirmationText(selectedItems), Runnable {
|
||||||
|
selectedItems.forEach { _, item ->
|
||||||
|
quickWizard.remove(item.position)
|
||||||
|
rxBus.send(EventQuickWizardChange())
|
||||||
|
}
|
||||||
|
actionHelper.finish()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||||
|
menuInflater.inflate(R.menu.menu_actions, menu)
|
||||||
|
return super.onCreateOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
override fun onOptionsItemSelected(item: MenuItem): Boolean =
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
android.R.id.home -> {
|
android.R.id.home -> {
|
||||||
|
@ -220,6 +182,17 @@ class QuickWizardListActivity : DaggerAppCompatActivityWithResult() {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> false
|
else -> actionHelper.onOptionsItemSelected(item)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getConfirmationText(selectedItems: SparseArray<QuickWizardEntry>): String {
|
||||||
|
if (selectedItems.size() == 1) {
|
||||||
|
val entry = selectedItems.valueAt(0)
|
||||||
|
return "${rh.gs(R.string.remove_button)} ${entry.buttonText()} ${rh.gs(R.string.format_carbs, entry.carbs())}\n" +
|
||||||
|
"${dateUtil.timeString(entry.validFromDate())} - ${dateUtil.timeString(entry.validToDate())}"
|
||||||
|
}
|
||||||
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,7 +105,7 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
|
||||||
binding.from.setOnClickListener {
|
binding.from.setOnClickListener {
|
||||||
context?.let {
|
context?.let {
|
||||||
TimePickerDialog(
|
TimePickerDialog(
|
||||||
it, R.style.MaterialPickerTheme,
|
it,
|
||||||
fromTimeSetListener,
|
fromTimeSetListener,
|
||||||
T.secs(fromSeconds.toLong()).hours().toInt(),
|
T.secs(fromSeconds.toLong()).hours().toInt(),
|
||||||
T.secs((fromSeconds % 3600).toLong()).mins().toInt(),
|
T.secs((fromSeconds % 3600).toLong()).mins().toInt(),
|
||||||
|
@ -124,7 +124,7 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener {
|
||||||
binding.to.setOnClickListener {
|
binding.to.setOnClickListener {
|
||||||
context?.let {
|
context?.let {
|
||||||
TimePickerDialog(
|
TimePickerDialog(
|
||||||
it, R.style.MaterialPickerTheme,
|
it,
|
||||||
toTimeSetListener,
|
toTimeSetListener,
|
||||||
T.secs(toSeconds.toLong()).hours().toInt(),
|
T.secs(toSeconds.toLong()).hours().toInt(),
|
||||||
T.secs((toSeconds % 3600).toLong()).mins().toInt(),
|
T.secs((toSeconds % 3600).toLong()).mins().toInt(),
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.events
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event
|
|
||||||
|
|
||||||
class EventUpdateOverviewBg(val from: String) : Event()
|
|
|
@ -1,5 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.events
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event
|
|
||||||
|
|
||||||
class EventUpdateOverviewExtendedBolus(val from: String) : Event()
|
|
|
@ -1,5 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.events
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event
|
|
||||||
|
|
||||||
class EventUpdateOverviewProfile(val from: String) : Event()
|
|
|
@ -1,5 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.events
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event
|
|
||||||
|
|
||||||
class EventUpdateOverviewTemporaryBasal(val from: String) : Event()
|
|
|
@ -1,5 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.events
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event
|
|
||||||
|
|
||||||
class EventUpdateOverviewTemporaryTarget(val from: String) : Event()
|
|
|
@ -1,5 +0,0 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.events
|
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event
|
|
||||||
|
|
||||||
class EventUpdateOverviewTime(val from: String) : Event()
|
|
|
@ -66,7 +66,7 @@ class GraphData(
|
||||||
addSeries(AreaGraphSeries(inRangeAreaDataPoints).also {
|
addSeries(AreaGraphSeries(inRangeAreaDataPoints).also {
|
||||||
it.color = 0
|
it.color = 0
|
||||||
it.isDrawBackground = true
|
it.isDrawBackground = true
|
||||||
it.backgroundColor = rh.gc(R.color.inrangebackground)
|
it.backgroundColor = rh.gac(graph.context,R.attr.inrangeBackground)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +88,11 @@ class GraphData(
|
||||||
addSeries(overviewData.treatmentsSeries)
|
addSeries(overviewData.treatmentsSeries)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addTherapyEvents() {
|
||||||
|
maxY = maxOf(maxY, overviewData.maxTherapyEventValue)
|
||||||
|
addSeries(overviewData.therapyEventSeries)
|
||||||
|
}
|
||||||
|
|
||||||
fun addActivity(scale: Double) {
|
fun addActivity(scale: Double) {
|
||||||
addSeries(overviewData.activitySeries)
|
addSeries(overviewData.activitySeries)
|
||||||
addSeries(overviewData.activityPredictionSeries)
|
addSeries(overviewData.activityPredictionSeries)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import info.nightscout.androidaps.core.R
|
import info.nightscout.androidaps.core.R
|
||||||
import info.nightscout.androidaps.database.entities.Bolus
|
import info.nightscout.androidaps.database.entities.Bolus
|
||||||
|
@ -28,13 +29,11 @@ class BolusDataPoint @Inject constructor(
|
||||||
override val shape
|
override val shape
|
||||||
get() = if (data.type == Bolus.Type.SMB) PointsWithLabelGraphSeries.Shape.SMB else PointsWithLabelGraphSeries.Shape.BOLUS
|
get() = if (data.type == Bolus.Type.SMB) PointsWithLabelGraphSeries.Shape.SMB else PointsWithLabelGraphSeries.Shape.BOLUS
|
||||||
|
|
||||||
override val color
|
override fun color(context: Context?): Int =
|
||||||
get() =
|
if (data.type == Bolus.Type.SMB) rh.gac(context, R.attr.smbColor)
|
||||||
when {
|
else if (data.isValid) rh.gac(context, R.attr.bolusDataPointColor)
|
||||||
data.type == Bolus.Type.SMB -> rh.gc(R.color.tempbasal)
|
else rh.gac(context, R.attr.alarmColor)
|
||||||
data.isValid -> Color.CYAN
|
|
||||||
else -> rh.gc(android.R.color.holo_red_light)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setY(y: Double) {
|
override fun setY(y: Double) {
|
||||||
yValue = y
|
yValue = y
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import info.nightscout.androidaps.core.R
|
import info.nightscout.androidaps.core.R
|
||||||
import info.nightscout.androidaps.database.entities.Carbs
|
import info.nightscout.androidaps.database.entities.Carbs
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
@ -18,7 +19,10 @@ class CarbsDataPoint @Inject constructor(
|
||||||
override val duration = 0L
|
override val duration = 0L
|
||||||
override val size = 2f
|
override val size = 2f
|
||||||
override val shape = PointsWithLabelGraphSeries.Shape.CARBS
|
override val shape = PointsWithLabelGraphSeries.Shape.CARBS
|
||||||
override val color get() = if (data.isValid) rh.gc(R.color.carbs) else rh.gc(android.R.color.holo_red_light)
|
|
||||||
|
override fun color(context: Context?): Int {
|
||||||
|
return if (data.isValid) rh.gac(context, R.attr.cobColor) else rh.gac(context, R.attr.alarmColor)
|
||||||
|
}
|
||||||
|
|
||||||
override fun setY(y: Double) {
|
override fun setY(y: Double) {
|
||||||
yValue = y
|
yValue = y
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import info.nightscout.androidaps.core.R
|
||||||
import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
|
import info.nightscout.androidaps.database.entities.EffectiveProfileSwitch
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class EffectiveProfileSwitchDataPoint @Inject constructor(
|
class EffectiveProfileSwitchDataPoint @Inject constructor(
|
||||||
val data: EffectiveProfileSwitch
|
val data: EffectiveProfileSwitch,
|
||||||
|
private val rh: ResourceHelper
|
||||||
) : DataPointWithLabelInterface {
|
) : DataPointWithLabelInterface {
|
||||||
|
|
||||||
private var yValue = 0.0
|
private var yValue = 0.0
|
||||||
|
@ -21,5 +25,7 @@ class EffectiveProfileSwitchDataPoint @Inject constructor(
|
||||||
override val duration = 0L
|
override val duration = 0L
|
||||||
override val shape = PointsWithLabelGraphSeries.Shape.PROFILE
|
override val shape = PointsWithLabelGraphSeries.Shape.PROFILE
|
||||||
override val size = 10f
|
override val size = 10f
|
||||||
override val color = Color.CYAN
|
override fun color(context: Context?): Int {
|
||||||
|
return rh.gac(context, R.attr.profileSwitchColor)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,16 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import info.nightscout.androidaps.core.R
|
||||||
import info.nightscout.androidaps.database.entities.ExtendedBolus
|
import info.nightscout.androidaps.database.entities.ExtendedBolus
|
||||||
import info.nightscout.androidaps.extensions.toStringTotal
|
import info.nightscout.androidaps.extensions.toStringTotal
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class ExtendedBolusDataPoint @Inject constructor(
|
class ExtendedBolusDataPoint @Inject constructor(
|
||||||
val data: ExtendedBolus
|
val data: ExtendedBolus,
|
||||||
|
private val rh: ResourceHelper
|
||||||
) : DataPointWithLabelInterface {
|
) : DataPointWithLabelInterface {
|
||||||
|
|
||||||
private var yValue = 0.0
|
private var yValue = 0.0
|
||||||
|
@ -17,7 +21,9 @@ class ExtendedBolusDataPoint @Inject constructor(
|
||||||
override val duration get() = data.duration
|
override val duration get() = data.duration
|
||||||
override val size = 10f
|
override val size = 10f
|
||||||
override val shape = PointsWithLabelGraphSeries.Shape.EXTENDEDBOLUS
|
override val shape = PointsWithLabelGraphSeries.Shape.EXTENDEDBOLUS
|
||||||
override val color = Color.CYAN
|
override fun color(context: Context?): Int {
|
||||||
|
return rh.gac(context, R.attr.extBolusColor)
|
||||||
|
}
|
||||||
|
|
||||||
override fun setY(y: Double) {
|
override fun setY(y: Double) {
|
||||||
yValue = y
|
yValue = y
|
||||||
|
|
|
@ -261,7 +261,7 @@ public class FixedLineGraphSeries<E extends DataPointInterface> extends BaseSeri
|
||||||
//fix: last value not drawn as datapoint. Draw first point here, and then on every step the end values (above)
|
//fix: last value not drawn as datapoint. Draw first point here, and then on every step the end values (above)
|
||||||
// float first_X = (float) x + (graphLeft + 1);
|
// float first_X = (float) x + (graphLeft + 1);
|
||||||
// float first_Y = (float) (graphTop - y) + graphHeight;
|
// float first_Y = (float) (graphTop - y) + graphHeight;
|
||||||
//TODO canvas.drawCircle(first_X, first_Y, dataPointsRadius, mPaint);
|
// canvas.drawCircle(first_X, first_Y, dataPointsRadius, mPaint);
|
||||||
}
|
}
|
||||||
lastEndY = orgY;
|
lastEndY = orgY;
|
||||||
lastEndX = orgX;
|
lastEndX = orgX;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.core.R
|
import info.nightscout.androidaps.core.R
|
||||||
import info.nightscout.androidaps.database.entities.GlucoseValue
|
import info.nightscout.androidaps.database.entities.GlucoseValue
|
||||||
|
@ -27,30 +28,28 @@ class GlucoseValueDataPoint @Inject constructor(
|
||||||
override val duration = 0L
|
override val duration = 0L
|
||||||
override val shape get() = if (isPrediction) PointsWithLabelGraphSeries.Shape.PREDICTION else PointsWithLabelGraphSeries.Shape.BG
|
override val shape get() = if (isPrediction) PointsWithLabelGraphSeries.Shape.PREDICTION else PointsWithLabelGraphSeries.Shape.BG
|
||||||
override val size = 1f
|
override val size = 1f
|
||||||
override val color: Int
|
override fun color(context: Context?): Int {
|
||||||
get() {
|
val units = profileFunction.getUnits()
|
||||||
val units = profileFunction.getUnits()
|
val lowLine = defaultValueHelper.determineLowLine()
|
||||||
val lowLine = defaultValueHelper.determineLowLine()
|
val highLine = defaultValueHelper.determineHighLine()
|
||||||
val highLine = defaultValueHelper.determineHighLine()
|
return when {
|
||||||
return when {
|
isPrediction -> predictionColor(context)
|
||||||
isPrediction -> predictionColor
|
valueToUnits(units) < lowLine -> rh.gac(context, R.attr.bgLow)
|
||||||
valueToUnits(units) < lowLine -> rh.gc(R.color.low)
|
valueToUnits(units) > highLine -> rh.gac(context, R.attr.highColor)
|
||||||
valueToUnits(units) > highLine -> rh.gc(R.color.high)
|
else -> rh.gac(context, R.attr.bgInRange)
|
||||||
else -> rh.gc(R.color.inrange)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val predictionColor: Int
|
private fun predictionColor (context: Context?): Int {
|
||||||
get() {
|
|
||||||
return when (data.sourceSensor) {
|
return when (data.sourceSensor) {
|
||||||
GlucoseValue.SourceSensor.IOB_PREDICTION -> rh.gc(R.color.iob)
|
GlucoseValue.SourceSensor.IOB_PREDICTION -> rh.gac(context, R.attr.iobColor)
|
||||||
GlucoseValue.SourceSensor.COB_PREDICTION -> rh.gc(R.color.cob)
|
GlucoseValue.SourceSensor.COB_PREDICTION -> rh.gac(context, R.attr.cobColor)
|
||||||
GlucoseValue.SourceSensor.A_COB_PREDICTION -> -0x7f000001 and rh.gc(R.color.cob)
|
GlucoseValue.SourceSensor.A_COB_PREDICTION -> -0x7f000001 and rh.gac(context, R.attr.cobColor)
|
||||||
GlucoseValue.SourceSensor.UAM_PREDICTION -> rh.gc(R.color.uam)
|
GlucoseValue.SourceSensor.UAM_PREDICTION -> rh.gac(context, R.attr.uamColor)
|
||||||
GlucoseValue.SourceSensor.ZT_PREDICTION -> rh.gc(R.color.zt)
|
GlucoseValue.SourceSensor.ZT_PREDICTION -> rh.gac(context, R.attr.ztColor)
|
||||||
else -> R.color.white
|
else -> rh.gac( context,R.attr.defaultTextColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val isPrediction: Boolean
|
private val isPrediction: Boolean
|
||||||
get() = data.sourceSensor == GlucoseValue.SourceSensor.IOB_PREDICTION ||
|
get() = data.sourceSensor == GlucoseValue.SourceSensor.IOB_PREDICTION ||
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.core.R
|
import info.nightscout.androidaps.core.R
|
||||||
import info.nightscout.androidaps.data.InMemoryGlucoseValue
|
import info.nightscout.androidaps.data.InMemoryGlucoseValue
|
||||||
|
@ -24,5 +25,7 @@ class InMemoryGlucoseValueDataPoint @Inject constructor(
|
||||||
override val duration = 0L
|
override val duration = 0L
|
||||||
override val shape = PointsWithLabelGraphSeries.Shape.BUCKETED_BG
|
override val shape = PointsWithLabelGraphSeries.Shape.BUCKETED_BG
|
||||||
override val size = 0.3f
|
override val size = 0.3f
|
||||||
override val color get() = rh.gc(R.color.white)
|
override fun color(context: Context?): Int {
|
||||||
|
return rh.gac(context, R.attr.inMemoryColor)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
package info.nightscout.androidaps.plugins.general.overview.graphExtensions
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.core.R
|
import info.nightscout.androidaps.core.R
|
||||||
|
@ -59,14 +60,14 @@ class TherapyEventDataPoint @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override val size get() = if (rh.gb(R.bool.isTablet)) 12.0f else 10.0f
|
override val size get() = if (rh.gb(R.bool.isTablet)) 12.0f else 10.0f
|
||||||
override val color
|
override fun color(context: Context?): Int {
|
||||||
get() =
|
return when (data.type) {
|
||||||
when (data.type) {
|
TherapyEvent.Type.ANNOUNCEMENT -> rh.gac(context, R.attr.notificationAnnouncement)
|
||||||
TherapyEvent.Type.ANNOUNCEMENT -> rh.gc(R.color.notificationAnnouncement)
|
TherapyEvent.Type.NS_MBG -> rh.gac(context, R.attr.therapyEvent_NS_MBG)
|
||||||
TherapyEvent.Type.NS_MBG -> Color.RED
|
TherapyEvent.Type.FINGER_STICK_BG_VALUE -> rh.gac(context, R.attr.therapyEvent_FINGER_STICK_BG_VALUE)
|
||||||
TherapyEvent.Type.FINGER_STICK_BG_VALUE -> Color.RED
|
TherapyEvent.Type.EXERCISE -> rh.gac(context, R.attr.therapyEvent_EXERCISE)
|
||||||
TherapyEvent.Type.EXERCISE -> Color.BLUE
|
TherapyEvent.Type.APS_OFFLINE -> rh.gac(context, R.attr.therapyEvent_APS_OFFLINE) and -0x7f000001
|
||||||
TherapyEvent.Type.APS_OFFLINE -> Color.GRAY and -0x7f000001
|
else -> rh.gac(context, R.attr.therapyEvent_Default)
|
||||||
else -> Color.GRAY
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -164,11 +164,11 @@ class NotificationStore @Inject constructor(
|
||||||
@Suppress("SetTextI18n")
|
@Suppress("SetTextI18n")
|
||||||
holder.binding.text.text = dateUtil.timeString(notification.date) + " " + notification.text
|
holder.binding.text.text = dateUtil.timeString(notification.date) + " " + notification.text
|
||||||
when (notification.level) {
|
when (notification.level) {
|
||||||
Notification.URGENT -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationUrgent))
|
Notification.URGENT -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationUrgent))
|
||||||
Notification.NORMAL -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationNormal))
|
Notification.NORMAL -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationNormal))
|
||||||
Notification.LOW -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationLow))
|
Notification.LOW -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationLow))
|
||||||
Notification.INFO -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationInfo))
|
Notification.INFO -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationInfo))
|
||||||
Notification.ANNOUNCEMENT -> holder.binding.cv.setBackgroundColor(rh.gc(R.color.notificationAnnouncement))
|
Notification.ANNOUNCEMENT -> holder.binding.cv.setBackgroundColor(rh.gac(R.attr.notificationAnnouncement))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,6 @@ class DummyService : DaggerService() {
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
// TODO: I guess this was moved here in order to adhere to the 5 seconds rule to call "startForeground" after a Service was called as Foreground service?
|
|
||||||
// As onCreate() is not called every time a service is started, copied to onStartCommand().
|
|
||||||
try {
|
try {
|
||||||
aapsLogger.debug("Starting DummyService with ID ${notificationHolder.notificationID} notification ${notificationHolder.notification}")
|
aapsLogger.debug("Starting DummyService with ID ${notificationHolder.notificationID} notification ${notificationHolder.notification}")
|
||||||
startForeground(notificationHolder.notificationID, notificationHolder.notification)
|
startForeground(notificationHolder.notificationID, notificationHolder.notification)
|
||||||
|
|
|
@ -9,17 +9,20 @@ import androidx.core.app.RemoteInput
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
import info.nightscout.androidaps.events.*
|
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
||||||
|
import info.nightscout.androidaps.events.EventInitializationChanged
|
||||||
|
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||||
|
import info.nightscout.androidaps.events.EventRefreshOverview
|
||||||
import info.nightscout.androidaps.extensions.toStringShort
|
import info.nightscout.androidaps.extensions.toStringShort
|
||||||
import info.nightscout.androidaps.extensions.valueToUnitsString
|
import info.nightscout.androidaps.extensions.valueToUnitsString
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider
|
||||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -72,26 +75,10 @@ class PersistentNotificationPlugin @Inject constructor(
|
||||||
.toObservable(EventRefreshOverview::class.java)
|
.toObservable(EventRefreshOverview::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventExtendedBolusChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventTempBasalChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventTreatmentChange::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventInitializationChanged::class.java)
|
.toObservable(EventInitializationChanged::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventEffectiveProfileSwitchChanged::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe({ triggerNotificationUpdate() }, fabricPrivacy::logException)
|
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventAutosensCalculationFinished::class.java)
|
.toObservable(EventAutosensCalculationFinished::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
|
|
|
@ -328,7 +328,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
} else if (lastBG != null) {
|
} else if (lastBG != null) {
|
||||||
val agoMilliseconds = dateUtil.now() - lastBG.timestamp
|
val agoMilliseconds = dateUtil.now() - lastBG.timestamp
|
||||||
val agoMin = (agoMilliseconds / 60.0 / 1000.0).toInt()
|
val agoMin = (agoMilliseconds / 60.0 / 1000.0).toInt()
|
||||||
reply = rh.gs(R.string.sms_lastbg) + " " + lastBG.valueToUnitsString(units) + " " + String.format(rh.gs(R.string.sms_minago), agoMin) + ", "
|
reply = rh.gs(R.string.sms_lastbg) + " " + lastBG.valueToUnitsString(units) + " " + rh.gs(R.string.sms_minago, agoMin) + ", "
|
||||||
}
|
}
|
||||||
val glucoseStatus = glucoseStatusProvider.glucoseStatusData
|
val glucoseStatus = glucoseStatusProvider.glucoseStatusData
|
||||||
if (glucoseStatus != null) reply += rh.gs(R.string.sms_delta) + " " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", "
|
if (glucoseStatus != null) reply += rh.gs(R.string.sms_delta) + " " + Profile.toUnitsString(glucoseStatus.delta, glucoseStatus.delta * Constants.MGDL_TO_MMOLL, units) + " " + units + ", "
|
||||||
|
@ -348,7 +348,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
"DISABLE", "STOP" -> {
|
"DISABLE", "STOP" -> {
|
||||||
if (loop.enabled) {
|
if (loop.enabled) {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_loopdisablereplywithcode), passCode)
|
val reply = rh.gs(R.string.smscommunicator_loopdisablereplywithcode, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -372,7 +372,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
"ENABLE", "START" -> {
|
"ENABLE", "START" -> {
|
||||||
if (!loop.enabled) {
|
if (!loop.enabled) {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_loopenablereplywithcode), passCode)
|
val reply = rh.gs(R.string.smscommunicator_loopenablereplywithcode, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -389,7 +389,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
|
|
||||||
"STATUS" -> {
|
"STATUS" -> {
|
||||||
val reply = if (loop.enabled) {
|
val reply = if (loop.enabled) {
|
||||||
if (loop.isSuspended) String.format(rh.gs(R.string.loopsuspendedfor), loop.minutesToEndOfSuspend())
|
if (loop.isSuspended) rh.gs(R.string.loopsuspendedfor, loop.minutesToEndOfSuspend())
|
||||||
else rh.gs(R.string.smscommunicator_loopisenabled)
|
else rh.gs(R.string.smscommunicator_loopisenabled)
|
||||||
} else
|
} else
|
||||||
rh.gs(R.string.loopisdisabled)
|
rh.gs(R.string.loopisdisabled)
|
||||||
|
@ -399,7 +399,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
|
|
||||||
"RESUME" -> {
|
"RESUME" -> {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_loopresumereplywithcode), passCode)
|
val reply = rh.gs(R.string.smscommunicator_loopresumereplywithcode, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -436,7 +436,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_suspendreplywithcode), duration, passCode)
|
val reply = rh.gs(R.string.smscommunicator_suspendreplywithcode, duration, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, duration) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, duration) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -515,7 +515,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
} else if ((divided.size == 2) && (divided[1].equals("CONNECT", ignoreCase = true))) {
|
} else if ((divided.size == 2) && (divided[1].equals("CONNECT", ignoreCase = true))) {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_pumpconnectwithcode), passCode)
|
val reply = rh.gs(R.string.smscommunicator_pumpconnectwithcode, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -548,7 +548,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_pumpdisconnectwithcode), duration, passCode)
|
val reply = rh.gs(R.string.smscommunicator_pumpdisconnectwithcode, duration, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -601,7 +601,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.noprofile)))
|
if (profile == null) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.noprofile)))
|
||||||
else {
|
else {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_profilereplywithcode), list[pIndex - 1], percentage, passCode)
|
val reply = rh.gs(R.string.smscommunicator_profilereplywithcode, list[pIndex - 1], percentage, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
val finalPercentage = percentage
|
val finalPercentage = percentage
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, list[pIndex - 1] as String, finalPercentage) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, list[pIndex - 1] as String, finalPercentage) {
|
||||||
|
@ -627,7 +627,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
private fun processBASAL(divided: Array<String>, receivedSms: Sms) {
|
private fun processBASAL(divided: Array<String>, receivedSms: Sms) {
|
||||||
if (divided[1].uppercase(Locale.getDefault()) == "CANCEL" || divided[1].uppercase(Locale.getDefault()) == "STOP") {
|
if (divided[1].uppercase(Locale.getDefault()) == "CANCEL" || divided[1].uppercase(Locale.getDefault()) == "STOP") {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_basalstopreplywithcode), passCode)
|
val reply = rh.gs(R.string.smscommunicator_basalstopreplywithcode, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -662,14 +662,14 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
else {
|
else {
|
||||||
tempBasalPct = constraintChecker.applyBasalPercentConstraints(Constraint(tempBasalPct), profile).value()
|
tempBasalPct = constraintChecker.applyBasalPercentConstraints(Constraint(tempBasalPct), profile).value()
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_basalpctreplywithcode), tempBasalPct, duration, passCode)
|
val reply = rh.gs(R.string.smscommunicator_basalpctreplywithcode, tempBasalPct, duration, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, tempBasalPct, duration) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, tempBasalPct, duration) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
commandQueue.tempBasalPercent(anInteger(), secondInteger(), true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() {
|
commandQueue.tempBasalPercent(anInteger(), secondInteger(), true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
var replyText = if (result.isPercent) String.format(rh.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration) else String.format(rh.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration)
|
var replyText = if (result.isPercent) rh.gs(R.string.smscommunicator_tempbasalset_percent, result.percent, result.duration) else rh.gs(R.string.smscommunicator_tempbasalset, result.absolute, result.duration)
|
||||||
replyText += "\n" + activePlugin.activePump.shortStatus(true)
|
replyText += "\n" + activePlugin.activePump.shortStatus(true)
|
||||||
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
||||||
if (result.isPercent)
|
if (result.isPercent)
|
||||||
|
@ -706,15 +706,15 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
else {
|
else {
|
||||||
tempBasal = constraintChecker.applyBasalConstraints(Constraint(tempBasal), profile).value()
|
tempBasal = constraintChecker.applyBasalConstraints(Constraint(tempBasal), profile).value()
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_basalreplywithcode), tempBasal, duration, passCode)
|
val reply = rh.gs(R.string.smscommunicator_basalreplywithcode, tempBasal, duration, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, tempBasal, duration) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, tempBasal, duration) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
commandQueue.tempBasalAbsolute(aDouble(), secondInteger(), true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() {
|
commandQueue.tempBasalAbsolute(aDouble(), secondInteger(), true, profile, PumpSync.TemporaryBasalType.NORMAL, object : Callback() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
var replyText = if (result.isPercent) String.format(rh.gs(R.string.smscommunicator_tempbasalset_percent), result.percent, result.duration)
|
var replyText = if (result.isPercent) rh.gs(R.string.smscommunicator_tempbasalset_percent, result.percent, result.duration)
|
||||||
else String.format(rh.gs(R.string.smscommunicator_tempbasalset), result.absolute, result.duration)
|
else rh.gs(R.string.smscommunicator_tempbasalset, result.absolute, result.duration)
|
||||||
replyText += "\n" + activePlugin.activePump.shortStatus(true)
|
replyText += "\n" + activePlugin.activePump.shortStatus(true)
|
||||||
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
||||||
if (result.isPercent)
|
if (result.isPercent)
|
||||||
|
@ -743,7 +743,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
private fun processEXTENDED(divided: Array<String>, receivedSms: Sms) {
|
private fun processEXTENDED(divided: Array<String>, receivedSms: Sms) {
|
||||||
if (divided[1].uppercase(Locale.getDefault()) == "CANCEL" || divided[1].uppercase(Locale.getDefault()) == "STOP") {
|
if (divided[1].uppercase(Locale.getDefault()) == "CANCEL" || divided[1].uppercase(Locale.getDefault()) == "STOP") {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_extendedstopreplywithcode), passCode)
|
val reply = rh.gs(R.string.smscommunicator_extendedstopreplywithcode, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -773,14 +773,14 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
if (extended == 0.0 || duration == 0) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.wrongformat)))
|
if (extended == 0.0 || duration == 0) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.wrongformat)))
|
||||||
else {
|
else {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_extendedreplywithcode), extended, duration, passCode)
|
val reply = rh.gs(R.string.smscommunicator_extendedreplywithcode, extended, duration, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, extended, duration) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, extended, duration) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
commandQueue.extendedBolus(aDouble(), secondInteger(), object : Callback() {
|
commandQueue.extendedBolus(aDouble(), secondInteger(), object : Callback() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
var replyText = String.format(rh.gs(R.string.smscommunicator_extendedset), aDouble, duration)
|
var replyText = rh.gs(R.string.smscommunicator_extendedset, aDouble, duration)
|
||||||
if (config.APS) replyText += "\n" + rh.gs(R.string.loopsuspended)
|
if (config.APS) replyText += "\n" + rh.gs(R.string.loopsuspended)
|
||||||
replyText += "\n" + activePlugin.activePump.shortStatus(true)
|
replyText += "\n" + activePlugin.activePump.shortStatus(true)
|
||||||
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
||||||
|
@ -817,9 +817,9 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
} else if (bolus > 0.0) {
|
} else if (bolus > 0.0) {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = if (isMeal)
|
val reply = if (isMeal)
|
||||||
String.format(rh.gs(R.string.smscommunicator_mealbolusreplywithcode), bolus, passCode)
|
rh.gs(R.string.smscommunicator_mealbolusreplywithcode, bolus, passCode)
|
||||||
else
|
else
|
||||||
String.format(rh.gs(R.string.smscommunicator_bolusreplywithcode), bolus, passCode)
|
rh.gs(R.string.smscommunicator_bolusreplywithcode, bolus, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, bolus) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, bolus) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -833,9 +833,9 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (resultSuccess) {
|
if (resultSuccess) {
|
||||||
var replyText = if (isMeal)
|
var replyText = if (isMeal)
|
||||||
String.format(rh.gs(R.string.smscommunicator_mealbolusdelivered), resultBolusDelivered)
|
rh.gs(R.string.smscommunicator_mealbolusdelivered, resultBolusDelivered)
|
||||||
else
|
else
|
||||||
String.format(rh.gs(R.string.smscommunicator_bolusdelivered), resultBolusDelivered)
|
rh.gs(R.string.smscommunicator_bolusdelivered, resultBolusDelivered)
|
||||||
replyText += "\n" + activePlugin.activePump.shortStatus(true)
|
replyText += "\n" + activePlugin.activePump.shortStatus(true)
|
||||||
lastRemoteBolusTime = dateUtil.now()
|
lastRemoteBolusTime = dateUtil.now()
|
||||||
if (isMeal) {
|
if (isMeal) {
|
||||||
|
@ -866,7 +866,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
val tt = if (currentProfile.units == GlucoseUnit.MMOL) {
|
val tt = if (currentProfile.units == GlucoseUnit.MMOL) {
|
||||||
DecimalFormatter.to1Decimal(eatingSoonTT)
|
DecimalFormatter.to1Decimal(eatingSoonTT)
|
||||||
} else DecimalFormatter.to0Decimal(eatingSoonTT)
|
} else DecimalFormatter.to0Decimal(eatingSoonTT)
|
||||||
replyText += "\n" + String.format(rh.gs(R.string.smscommunicator_mealbolusdelivered_tt), tt, eatingSoonTTDuration)
|
replyText += "\n" + rh.gs(R.string.smscommunicator_mealbolusdelivered_tt, tt, eatingSoonTTDuration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
||||||
|
@ -920,7 +920,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
if (grams == 0) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.wrongformat)))
|
if (grams == 0) sendSMS(Sms(receivedSms.phoneNumber, rh.gs(R.string.wrongformat)))
|
||||||
else {
|
else {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_carbsreplywithcode), grams, dateUtil.timeString(time), passCode)
|
val reply = rh.gs(R.string.smscommunicator_carbsreplywithcode, grams, dateUtil.timeString(time), passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, grams, time) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = true, grams, time) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -930,7 +930,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
commandQueue.bolus(detailedBolusInfo, object : Callback() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
var replyText = String.format(rh.gs(R.string.smscommunicator_carbsset), anInteger)
|
var replyText = rh.gs(R.string.smscommunicator_carbsset, anInteger)
|
||||||
replyText += "\n" + activePlugin.activePump.shortStatus(true)
|
replyText += "\n" + activePlugin.activePump.shortStatus(true)
|
||||||
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
||||||
uel.log(Action.CARBS, Sources.SMS, activePlugin.activePump.shortStatus(true) + ": " + rh.gs(R.string.smscommunicator_carbsset, anInteger),
|
uel.log(Action.CARBS, Sources.SMS, activePlugin.activePump.shortStatus(true) + ": " + rh.gs(R.string.smscommunicator_carbsset, anInteger),
|
||||||
|
@ -956,7 +956,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
val isStop = divided[1].equals("STOP", ignoreCase = true) || divided[1].equals("CANCEL", ignoreCase = true)
|
val isStop = divided[1].equals("STOP", ignoreCase = true) || divided[1].equals("CANCEL", ignoreCase = true)
|
||||||
if (isMeal || isActivity || isHypo) {
|
if (isMeal || isActivity || isHypo) {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_temptargetwithcode), divided[1].uppercase(Locale.getDefault()), passCode)
|
val reply = rh.gs(R.string.smscommunicator_temptargetwithcode, divided[1].uppercase(Locale.getDefault()), passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -1009,7 +1009,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
|
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
|
||||||
})
|
})
|
||||||
val ttString = if (units == GlucoseUnit.MMOL) DecimalFormatter.to1Decimal(tt) else DecimalFormatter.to0Decimal(tt)
|
val ttString = if (units == GlucoseUnit.MMOL) DecimalFormatter.to1Decimal(tt) else DecimalFormatter.to0Decimal(tt)
|
||||||
val replyText = String.format(rh.gs(R.string.smscommunicator_tt_set), ttString, ttDuration)
|
val replyText = rh.gs(R.string.smscommunicator_tt_set, ttString, ttDuration)
|
||||||
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
||||||
uel.log(Action.TT, Sources.SMS,
|
uel.log(Action.TT, Sources.SMS,
|
||||||
ValueWithUnit.fromGlucoseUnit(tt, units.asText),
|
ValueWithUnit.fromGlucoseUnit(tt, units.asText),
|
||||||
|
@ -1018,7 +1018,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
})
|
})
|
||||||
} else if (isStop) {
|
} else if (isStop) {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_temptargetcancel), passCode)
|
val reply = rh.gs(R.string.smscommunicator_temptargetcancel, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -1028,7 +1028,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
}, {
|
}, {
|
||||||
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
|
aapsLogger.error(LTag.DATABASE, "Error while saving temporary target", it)
|
||||||
})
|
})
|
||||||
val replyText = String.format(rh.gs(R.string.smscommunicator_tt_canceled))
|
val replyText = rh.gs(R.string.smscommunicator_tt_canceled)
|
||||||
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
||||||
uel.log(Action.CANCEL_TT, Sources.SMS, rh.gs(R.string.smscommunicator_tt_canceled),
|
uel.log(Action.CANCEL_TT, Sources.SMS, rh.gs(R.string.smscommunicator_tt_canceled),
|
||||||
ValueWithUnit.SimpleString(rh.gsNotLocalised(R.string.smscommunicator_tt_canceled)))
|
ValueWithUnit.SimpleString(rh.gsNotLocalised(R.string.smscommunicator_tt_canceled)))
|
||||||
|
@ -1043,12 +1043,12 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
|| divided[1].equals("DISABLE", ignoreCase = true))
|
|| divided[1].equals("DISABLE", ignoreCase = true))
|
||||||
if (isStop) {
|
if (isStop) {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_stopsmswithcode), passCode)
|
val reply = rh.gs(R.string.smscommunicator_stopsmswithcode, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
sp.putBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)
|
sp.putBoolean(R.string.key_smscommunicator_remotecommandsallowed, false)
|
||||||
val replyText = String.format(rh.gs(R.string.smscommunicator_stoppedsms))
|
val replyText = rh.gs(R.string.smscommunicator_stoppedsms)
|
||||||
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
sendSMSToAllNumbers(Sms(receivedSms.phoneNumber, replyText))
|
||||||
uel.log(Action.STOP_SMS, Sources.SMS, rh.gs(R.string.smscommunicator_stoppedsms),
|
uel.log(Action.STOP_SMS, Sources.SMS, rh.gs(R.string.smscommunicator_stoppedsms),
|
||||||
ValueWithUnit.SimpleString(rh.gsNotLocalised(R.string.smscommunicator_stoppedsms)))
|
ValueWithUnit.SimpleString(rh.gsNotLocalised(R.string.smscommunicator_stoppedsms)))
|
||||||
|
@ -1061,7 +1061,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
val cal = SafeParse.stringToDouble(divided[1])
|
val cal = SafeParse.stringToDouble(divided[1])
|
||||||
if (cal > 0.0) {
|
if (cal > 0.0) {
|
||||||
val passCode = generatePassCode()
|
val passCode = generatePassCode()
|
||||||
val reply = String.format(rh.gs(R.string.smscommunicator_calibrationreplywithcode), cal, passCode)
|
val reply = rh.gs(R.string.smscommunicator_calibrationreplywithcode, cal, passCode)
|
||||||
receivedSms.processed = true
|
receivedSms.processed = true
|
||||||
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false, cal) {
|
messageToConfirm = AuthRequest(injector, receivedSms, reply, passCode, object : SmsAction(pumpCommand = false, cal) {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
@ -1127,7 +1127,7 @@ class SmsCommunicatorPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generatePassCode(): String =
|
private fun generatePassCode(): String =
|
||||||
String.format(rh.gs(R.string.smscommunicator_code_from_authenticator_for), otp.name())
|
rh.gs(R.string.smscommunicator_code_from_authenticator_for, otp.name())
|
||||||
|
|
||||||
private fun stripAccents(str: String): String {
|
private fun stripAccents(str: String): String {
|
||||||
var s = str
|
var s = str
|
||||||
|
|
|
@ -31,7 +31,6 @@ import javax.inject.Inject
|
||||||
class SmsCommunicatorOtpActivity : NoSplashAppCompatActivity() {
|
class SmsCommunicatorOtpActivity : NoSplashAppCompatActivity() {
|
||||||
|
|
||||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||||
@Inject lateinit var rxBus: RxBus
|
|
||||||
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
|
@Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
|
||||||
@Inject lateinit var otp: OneTimePassword
|
@Inject lateinit var otp: OneTimePassword
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
package info.nightscout.androidaps.plugins.general.themes
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
|
||||||
|
import dagger.android.HasAndroidInjector
|
||||||
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.events.EventPreferenceChange
|
||||||
|
import info.nightscout.androidaps.events.EventThemeSwitch
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginBase
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginDescription
|
||||||
|
import info.nightscout.androidaps.interfaces.PluginType
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class ThemeSwitcherPlugin @Inject constructor(
|
||||||
|
injector: HasAndroidInjector,
|
||||||
|
aapsLogger: AAPSLogger,
|
||||||
|
rh: ResourceHelper,
|
||||||
|
private val sp: SP,
|
||||||
|
private val rxBus: RxBus,
|
||||||
|
) : PluginBase(PluginDescription()
|
||||||
|
.mainType(PluginType.GENERAL)
|
||||||
|
.neverVisible(true)
|
||||||
|
.alwaysEnabled(true)
|
||||||
|
.showInList(false)
|
||||||
|
.pluginName(R.string.dst_plugin_name),
|
||||||
|
aapsLogger, rh, injector
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val compositeDisposable = CompositeDisposable()
|
||||||
|
|
||||||
|
override fun onStart() {
|
||||||
|
compositeDisposable.add(rxBus.toObservable(EventPreferenceChange::class.java).subscribe {
|
||||||
|
if (it.isChanged(rh, id = R.string.key_use_dark_mode)) {
|
||||||
|
setThemeMode()
|
||||||
|
rxBus.send(EventThemeSwitch())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setThemeMode() {
|
||||||
|
val mode = when (sp.getString(R.string.key_use_dark_mode, "dark")) {
|
||||||
|
sp.getString(R.string.value_dark_theme, "dark") -> MODE_NIGHT_YES
|
||||||
|
sp.getString(R.string.value_light_theme, "light") -> MODE_NIGHT_NO
|
||||||
|
else -> MODE_NIGHT_FOLLOW_SYSTEM
|
||||||
|
}
|
||||||
|
AppCompatDelegate.setDefaultNightMode(mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
compositeDisposable.dispose()
|
||||||
|
}
|
||||||
|
}
|
|
@ -111,7 +111,7 @@ class ActionStringHandler @Inject constructor(
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun handleInitiate(actionString: String) {
|
private fun handleInitiate(actionString: String) {
|
||||||
//TODO: i18n
|
//TODO: i18n
|
||||||
Log.i("ActionStringHandler", "handleInitiate actionString=" + actionString)
|
Log.i("ActionStringHandler", "handleInitiate actionString=$actionString")
|
||||||
if (!sp.getBoolean(R.string.key_wear_control, false)) return
|
if (!sp.getBoolean(R.string.key_wear_control, false)) return
|
||||||
lastBolusWizard = null
|
lastBolusWizard = null
|
||||||
var rTitle = rh.gs(R.string.confirm).uppercase()
|
var rTitle = rh.gs(R.string.confirm).uppercase()
|
||||||
|
@ -640,10 +640,10 @@ class ActionStringHandler @Inject constructor(
|
||||||
var msg = ""
|
var msg = ""
|
||||||
//check for validity
|
//check for validity
|
||||||
if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) {
|
if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) {
|
||||||
msg += String.format(rh.gs(R.string.valueoutofrange), "Profile-Percentage") + "\n"
|
msg += rh.gs(R.string.valueoutofrange, "Profile-Percentage") + "\n"
|
||||||
}
|
}
|
||||||
if (timeshift < 0 || timeshift > 23) {
|
if (timeshift < 0 || timeshift > 23) {
|
||||||
msg += String.format(rh.gs(R.string.valueoutofrange), "Profile-Timeshift") + "\n"
|
msg += rh.gs(R.string.valueoutofrange, "Profile-Timeshift") + "\n"
|
||||||
}
|
}
|
||||||
val profile = profileFunction.getProfile()
|
val profile = profileFunction.getProfile()
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
|
|
|
@ -95,7 +95,7 @@ class WearPlugin @Inject constructor(
|
||||||
.toObservable(EventBolusRequested::class.java)
|
.toObservable(EventBolusRequested::class.java)
|
||||||
.observeOn(aapsSchedulers.io)
|
.observeOn(aapsSchedulers.io)
|
||||||
.subscribe({ event: EventBolusRequested ->
|
.subscribe({ event: EventBolusRequested ->
|
||||||
val status = String.format(rh.gs(R.string.bolusrequested), event.amount)
|
val status = rh.gs(R.string.bolusrequested, event.amount)
|
||||||
val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS)
|
val intent = Intent(ctx, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS)
|
||||||
intent.putExtra("progresspercent", 0)
|
intent.putExtra("progresspercent", 0)
|
||||||
intent.putExtra("progressstatus", status)
|
intent.putExtra("progressstatus", status)
|
||||||
|
|
|
@ -120,7 +120,7 @@ class SendToDataLayerThread extends AsyncTask<DataMap,Void,Void> {
|
||||||
}
|
}
|
||||||
state = 0;
|
state = 0;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, logPrefix + "Got exception in sendToWear: " + e.toString());
|
Log.e(TAG, logPrefix + "Got exception in sendToWear: " + e);
|
||||||
} finally {
|
} finally {
|
||||||
lastlock = 0;
|
lastlock = 0;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
|
@ -46,9 +46,6 @@ import info.nightscout.androidaps.interfaces.Loop;
|
||||||
import info.nightscout.androidaps.interfaces.PluginBase;
|
import info.nightscout.androidaps.interfaces.PluginBase;
|
||||||
import info.nightscout.androidaps.interfaces.Profile;
|
import info.nightscout.androidaps.interfaces.Profile;
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
import info.nightscout.androidaps.interfaces.ProfileFunction;
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry;
|
|
||||||
import info.nightscout.shared.logging.AAPSLogger;
|
|
||||||
import info.nightscout.shared.logging.LTag;
|
|
||||||
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus;
|
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus;
|
||||||
|
@ -64,7 +61,11 @@ import info.nightscout.androidaps.utils.DefaultValueHelper;
|
||||||
import info.nightscout.androidaps.utils.TrendCalculator;
|
import info.nightscout.androidaps.utils.TrendCalculator;
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
import info.nightscout.androidaps.utils.resources.ResourceHelper;
|
||||||
import info.nightscout.androidaps.utils.wizard.QuickWizard;
|
import info.nightscout.androidaps.utils.wizard.QuickWizard;
|
||||||
|
import info.nightscout.androidaps.utils.wizard.QuickWizardEntry;
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger;
|
||||||
|
import info.nightscout.shared.logging.LTag;
|
||||||
import info.nightscout.shared.sharedPreferences.SP;
|
import info.nightscout.shared.sharedPreferences.SP;
|
||||||
|
import info.nightscout.shared.weardata.WearUris;
|
||||||
|
|
||||||
public class WatchUpdaterService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
|
public class WatchUpdaterService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
|
||||||
@Inject public GlucoseStatusProvider glucoseStatusProvider;
|
@Inject public GlucoseStatusProvider glucoseStatusProvider;
|
||||||
|
@ -95,21 +96,6 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
public static final String ACTION_CANCEL_NOTIFICATION = WatchUpdaterService.class.getName().concat(".CancelNotification");
|
public static final String ACTION_CANCEL_NOTIFICATION = WatchUpdaterService.class.getName().concat(".CancelNotification");
|
||||||
|
|
||||||
private GoogleApiClient googleApiClient;
|
private GoogleApiClient googleApiClient;
|
||||||
public static final String WEARABLE_DATA_PATH = "/nightscout_watch_data";
|
|
||||||
public static final String WEARABLE_RESEND_PATH = "/nightscout_watch_data_resend";
|
|
||||||
private static final String WEARABLE_CANCELBOLUS_PATH = "/nightscout_watch_cancel_bolus";
|
|
||||||
public static final String WEARABLE_CONFIRM_ACTIONSTRING_PATH = "/nightscout_watch_confirmactionstring";
|
|
||||||
public static final String WEARABLE_INITIATE_ACTIONSTRING_PATH = "/nightscout_watch_initiateactionstring";
|
|
||||||
|
|
||||||
private static final String OPEN_SETTINGS_PATH = "/openwearsettings";
|
|
||||||
private static final String NEW_STATUS_PATH = "/sendstatustowear";
|
|
||||||
private static final String NEW_PREFERENCES_PATH = "/sendpreferencestowear";
|
|
||||||
private static final String QUICK_WIZARD_PATH = "/send_quick_wizard";
|
|
||||||
public static final String BASAL_DATA_PATH = "/nightscout_watch_basal";
|
|
||||||
public static final String BOLUS_PROGRESS_PATH = "/nightscout_watch_bolusprogress";
|
|
||||||
public static final String ACTION_CONFIRMATION_REQUEST_PATH = "/nightscout_watch_actionconfirmationrequest";
|
|
||||||
public static final String ACTION_CHANGECONFIRMATION_REQUEST_PATH = "/nightscout_watch_changeconfirmationrequest";
|
|
||||||
public static final String ACTION_CANCELNOTIFICATION_REQUEST_PATH = "/nightscout_watch_cancelnotificationrequest";
|
|
||||||
|
|
||||||
String TAG = "WatchUpdateService";
|
String TAG = "WatchUpdateService";
|
||||||
|
|
||||||
|
@ -259,21 +245,21 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
// Log.d(TAG, "onMessageRecieved: " + event);
|
// Log.d(TAG, "onMessageRecieved: " + event);
|
||||||
|
|
||||||
if (wearIntegration()) {
|
if (wearIntegration()) {
|
||||||
if (event != null && event.getPath().equals(WEARABLE_RESEND_PATH)) {
|
if (event != null && event.getPath().equals(WearUris.WEARABLE_RESEND_PATH)) {
|
||||||
resendData();
|
resendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event != null && event.getPath().equals(WEARABLE_CANCELBOLUS_PATH)) {
|
if (event != null && event.getPath().equals(WearUris.WEARABLE_CANCELBOLUS_PATH)) {
|
||||||
cancelBolus();
|
cancelBolus();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event != null && event.getPath().equals(WEARABLE_INITIATE_ACTIONSTRING_PATH)) {
|
if (event != null && event.getPath().equals(WearUris.WEARABLE_INITIATE_ACTIONSTRING_PATH)) {
|
||||||
String actionstring = new String(event.getData());
|
String actionstring = new String(event.getData());
|
||||||
aapsLogger.debug(LTag.WEAR, "Wear: " + actionstring);
|
aapsLogger.debug(LTag.WEAR, "Wear: " + actionstring);
|
||||||
rxBus.send(new EventWearInitiateAction(actionstring));
|
rxBus.send(new EventWearInitiateAction(actionstring));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event != null && event.getPath().equals(WEARABLE_CONFIRM_ACTIONSTRING_PATH)) {
|
if (event != null && event.getPath().equals(WearUris.WEARABLE_CONFIRM_ACTIONSTRING_PATH)) {
|
||||||
String actionstring = new String(event.getData());
|
String actionstring = new String(event.getData());
|
||||||
aapsLogger.debug(LTag.WEAR, "Wear Confirm: " + actionstring);
|
aapsLogger.debug(LTag.WEAR, "Wear Confirm: " + actionstring);
|
||||||
rxBus.send(new EventWearConfirmAction(actionstring));
|
rxBus.send(new EventWearConfirmAction(actionstring));
|
||||||
|
@ -299,7 +285,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
|
|
||||||
final DataMap dataMap = dataMapSingleBG(lastBG, glucoseStatus);
|
final DataMap dataMap = dataMapSingleBG(lastBG, glucoseStatus);
|
||||||
|
|
||||||
(new SendToDataLayerThread(WEARABLE_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, dataMap);
|
(new SendToDataLayerThread(WearUris.WEARABLE_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, dataMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -389,7 +375,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
dataMaps.add(dataMap);
|
dataMaps.add(dataMap);
|
||||||
}
|
}
|
||||||
entries.putDataMapArrayList("entries", dataMaps);
|
entries.putDataMapArrayList("entries", dataMaps);
|
||||||
(new SendToDataLayerThread(WEARABLE_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, entries);
|
(new SendToDataLayerThread(WearUris.WEARABLE_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, entries);
|
||||||
}
|
}
|
||||||
sendBasals();
|
sendBasals();
|
||||||
sendStatus();
|
sendStatus();
|
||||||
|
@ -423,13 +409,12 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
double endBasalValue = beginBasalValue;
|
double endBasalValue = beginBasalValue;
|
||||||
|
|
||||||
TemporaryBasal tb1 = iobCobCalculator.getTempBasalIncludingConvertedExtended(runningTime);
|
TemporaryBasal tb1 = iobCobCalculator.getTempBasalIncludingConvertedExtended(runningTime);
|
||||||
TemporaryBasal tb2 = iobCobCalculator.getTempBasalIncludingConvertedExtended(runningTime); //TODO for Adrian ... what's the meaning?
|
TemporaryBasal tb2;
|
||||||
double tb_before = beginBasalValue;
|
double tb_before = beginBasalValue;
|
||||||
double tb_amount = beginBasalValue;
|
double tb_amount = beginBasalValue;
|
||||||
long tb_start = runningTime;
|
long tb_start = runningTime;
|
||||||
|
|
||||||
if (tb1 != null) {
|
if (tb1 != null) {
|
||||||
tb_before = beginBasalValue;
|
|
||||||
Profile profileTB = profileFunction.getProfile(runningTime);
|
Profile profileTB = profileFunction.getProfile(runningTime);
|
||||||
if (profileTB != null) {
|
if (profileTB != null) {
|
||||||
tb_amount = TemporaryBasalExtensionKt.convertedToAbsolute(tb1, runningTime, profileTB);
|
tb_amount = TemporaryBasalExtensionKt.convertedToAbsolute(tb1, runningTime, profileTB);
|
||||||
|
@ -457,7 +442,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
tb2 = iobCobCalculator.getTempBasalIncludingConvertedExtended(runningTime);
|
tb2 = iobCobCalculator.getTempBasalIncludingConvertedExtended(runningTime);
|
||||||
|
|
||||||
if (tb1 == null && tb2 == null) {
|
if (tb1 == null && tb2 == null) {
|
||||||
//no temp stays no temp
|
; //no temp stays no temp
|
||||||
|
|
||||||
} else if (tb1 != null && tb2 == null) {
|
} else if (tb1 != null && tb2 == null) {
|
||||||
//temp is over -> push it
|
//temp is over -> push it
|
||||||
|
@ -529,7 +514,8 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
if (!predArray.isEmpty()) {
|
if (!predArray.isEmpty()) {
|
||||||
for (GlucoseValueDataPoint bg : predArray) {
|
for (GlucoseValueDataPoint bg : predArray) {
|
||||||
if (bg.getData().getValue() < 40) continue;
|
if (bg.getData().getValue() < 40) continue;
|
||||||
predictions.add(predictionMap(bg.getData().getTimestamp(), bg.getData().getValue(), bg.getPredictionColor()));
|
predictions.add(predictionMap(bg.getData().getTimestamp(),
|
||||||
|
bg.getData().getValue(), bg.color(null)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -540,7 +526,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
dm.putDataMapArrayList("temps", temps);
|
dm.putDataMapArrayList("temps", temps);
|
||||||
dm.putDataMapArrayList("boluses", boluses);
|
dm.putDataMapArrayList("boluses", boluses);
|
||||||
dm.putDataMapArrayList("predictions", predictions);
|
dm.putDataMapArrayList("predictions", predictions);
|
||||||
(new SendToDataLayerThread(BASAL_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, dm);
|
(new SendToDataLayerThread(WearUris.BASAL_DATA_PATH, googleApiClient)).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, dm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataMap tempDatamap(long startTime, double startBasal, long to, double toBasal, double amount) {
|
private DataMap tempDatamap(long startTime, double startBasal, long to, double toBasal, double amount) {
|
||||||
|
@ -582,7 +568,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
|
|
||||||
private void sendNotification() {
|
private void sendNotification() {
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
if (googleApiClient != null && googleApiClient.isConnected()) {
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(OPEN_SETTINGS_PATH);
|
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.OPEN_SETTINGS_PATH);
|
||||||
//unique content
|
//unique content
|
||||||
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
||||||
dataMapRequest.getDataMap().putString("openSettings", "openSettings");
|
dataMapRequest.getDataMap().putString("openSettings", "openSettings");
|
||||||
|
@ -595,7 +581,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
|
|
||||||
private void sendBolusProgress(int progresspercent, String status) {
|
private void sendBolusProgress(int progresspercent, String status) {
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
if (googleApiClient != null && googleApiClient.isConnected()) {
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(BOLUS_PROGRESS_PATH);
|
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.BOLUS_PROGRESS_PATH);
|
||||||
//unique content
|
//unique content
|
||||||
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
||||||
dataMapRequest.getDataMap().putString("bolusProgress", "bolusProgress");
|
dataMapRequest.getDataMap().putString("bolusProgress", "bolusProgress");
|
||||||
|
@ -610,7 +596,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
|
|
||||||
private void sendActionConfirmationRequest(String title, String message, String actionstring) {
|
private void sendActionConfirmationRequest(String title, String message, String actionstring) {
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
if (googleApiClient != null && googleApiClient.isConnected()) {
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(ACTION_CONFIRMATION_REQUEST_PATH);
|
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.ACTION_CONFIRMATION_REQUEST_PATH);
|
||||||
//unique content
|
//unique content
|
||||||
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
||||||
dataMapRequest.getDataMap().putString("actionConfirmationRequest", "actionConfirmationRequest");
|
dataMapRequest.getDataMap().putString("actionConfirmationRequest", "actionConfirmationRequest");
|
||||||
|
@ -629,7 +615,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
|
|
||||||
private void sendChangeConfirmationRequest(String title, String message, String actionstring) {
|
private void sendChangeConfirmationRequest(String title, String message, String actionstring) {
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
if (googleApiClient != null && googleApiClient.isConnected()) {
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(ACTION_CHANGECONFIRMATION_REQUEST_PATH);
|
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.ACTION_CHANGECONFIRMATION_REQUEST_PATH);
|
||||||
//unique content
|
//unique content
|
||||||
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
||||||
dataMapRequest.getDataMap().putString("changeConfirmationRequest", "changeConfirmationRequest");
|
dataMapRequest.getDataMap().putString("changeConfirmationRequest", "changeConfirmationRequest");
|
||||||
|
@ -648,7 +634,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
|
|
||||||
private void sendCancelNotificationRequest(String actionstring) {
|
private void sendCancelNotificationRequest(String actionstring) {
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
if (googleApiClient != null && googleApiClient.isConnected()) {
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(ACTION_CANCELNOTIFICATION_REQUEST_PATH);
|
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.ACTION_CANCELNOTIFICATION_REQUEST_PATH);
|
||||||
//unique content
|
//unique content
|
||||||
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
||||||
dataMapRequest.getDataMap().putString("cancelNotificationRequest", "cancelNotificationRequest");
|
dataMapRequest.getDataMap().putString("cancelNotificationRequest", "cancelNotificationRequest");
|
||||||
|
@ -704,7 +690,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
openApsStatus = nsDeviceStatus.getOpenApsTimestamp();
|
openApsStatus = nsDeviceStatus.getOpenApsTimestamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NEW_STATUS_PATH);
|
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.NEW_STATUS_PATH);
|
||||||
//unique content
|
//unique content
|
||||||
dataMapRequest.getDataMap().putString("externalStatusString", status);
|
dataMapRequest.getDataMap().putString("externalStatusString", status);
|
||||||
dataMapRequest.getDataMap().putString("iobSum", iobSum);
|
dataMapRequest.getDataMap().putString("iobSum", iobSum);
|
||||||
|
@ -734,14 +720,14 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
int percentage = sp.getInt(R.string.key_boluswizard_percentage, 100);
|
int percentage = sp.getInt(R.string.key_boluswizard_percentage, 100);
|
||||||
int maxCarbs = sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48);
|
int maxCarbs = sp.getInt(R.string.key_treatmentssafety_maxcarbs, 48);
|
||||||
double maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0);
|
double maxBolus = sp.getDouble(R.string.key_treatmentssafety_maxbolus, 3.0);
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NEW_PREFERENCES_PATH);
|
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.NEW_PREFERENCES_PATH);
|
||||||
//unique content
|
//unique content
|
||||||
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
dataMapRequest.getDataMap().putLong("timestamp", System.currentTimeMillis());
|
||||||
dataMapRequest.getDataMap().putBoolean(rh.gs(R.string.key_wear_control), wearcontrol);
|
dataMapRequest.getDataMap().putBoolean(rh.gs(R.string.key_wear_control), wearcontrol);
|
||||||
dataMapRequest.getDataMap().putBoolean(rh.gs(R.string.key_units_mgdl), mgdl);
|
dataMapRequest.getDataMap().putBoolean(rh.gs(R.string.key_units_mgdl), mgdl);
|
||||||
dataMapRequest.getDataMap().putInt(rh.gs(R.string.key_boluswizard_percentage), percentage);
|
dataMapRequest.getDataMap().putInt(rh.gs(R.string.key_boluswizard_percentage), percentage);
|
||||||
dataMapRequest.getDataMap().putInt(rh.gs(R.string.key_treatmentssafety_maxcarbs), maxCarbs);
|
dataMapRequest.getDataMap().putInt(rh.gs(R.string.key_treatmentssafety_maxcarbs), maxCarbs);
|
||||||
dataMapRequest.getDataMap().putDouble(rh.gs(R.string.key_treatmentssafety_maxbolus),maxBolus);
|
dataMapRequest.getDataMap().putDouble(rh.gs(R.string.key_treatmentssafety_maxbolus), maxBolus);
|
||||||
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
|
PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest();
|
||||||
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
|
Wearable.DataApi.putDataItem(googleApiClient, putDataRequest);
|
||||||
} else {
|
} else {
|
||||||
|
@ -753,14 +739,14 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
if (googleApiClient != null && googleApiClient.isConnected()) {
|
if (googleApiClient != null && googleApiClient.isConnected()) {
|
||||||
int size = quickWizard.size();
|
int size = quickWizard.size();
|
||||||
ArrayList<DataMap> entities = new ArrayList<>();
|
ArrayList<DataMap> entities = new ArrayList<>();
|
||||||
for(int i=0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
QuickWizardEntry q = quickWizard.get(i);
|
QuickWizardEntry q = quickWizard.get(i);
|
||||||
if (q.forDevice(QuickWizardEntry.DEVICE_WATCH)) {
|
if (q.forDevice(QuickWizardEntry.DEVICE_WATCH)) {
|
||||||
entities.add(quickMap(q));
|
entities.add(quickMap(q));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(QUICK_WIZARD_PATH);
|
PutDataMapRequest dataMapRequest = PutDataMapRequest.create(WearUris.QUICK_WIZARD_PATH);
|
||||||
|
|
||||||
DataMap dm = dataMapRequest.getDataMap();
|
DataMap dm = dataMapRequest.getDataMap();
|
||||||
dm.putLong("timestamp", System.currentTimeMillis());
|
dm.putLong("timestamp", System.currentTimeMillis());
|
||||||
|
@ -794,7 +780,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!((PluginBase)loop).isEnabled()) {
|
if (!((PluginBase) loop).isEnabled()) {
|
||||||
status += rh.gs(R.string.disabledloop) + "\n";
|
status += rh.gs(R.string.disabledloop) + "\n";
|
||||||
lastLoopStatus = false;
|
lastLoopStatus = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -44,6 +44,9 @@ class ActivityGraph : GraphView {
|
||||||
viewport.isXAxisBoundsManual = true
|
viewport.isXAxisBoundsManual = true
|
||||||
viewport.setMinX(0.0)
|
viewport.setMinX(0.0)
|
||||||
viewport.setMaxX((hours * 60).toDouble())
|
viewport.setMaxX((hours * 60).toDouble())
|
||||||
|
viewport.isYAxisBoundsManual = true
|
||||||
|
viewport.setMinY(0.0)
|
||||||
|
viewport.setMaxY(0.01)
|
||||||
gridLabelRenderer.numHorizontalLabels = (hours + 1).toInt()
|
gridLabelRenderer.numHorizontalLabels = (hours + 1).toInt()
|
||||||
gridLabelRenderer.horizontalAxisTitle = "[min]"
|
gridLabelRenderer.horizontalAxisTitle = "[min]"
|
||||||
secondScale.addSeries(LineGraphSeries(Array(iobArray.size) { i -> iobArray[i] }).also {
|
secondScale.addSeries(LineGraphSeries(Array(iobArray.size) { i -> iobArray[i] }).also {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package info.nightscout.androidaps.plugins.iob.iobCobCalculator
|
package info.nightscout.androidaps.plugins.iob.iobCobCalculator
|
||||||
|
|
||||||
import android.os.SystemClock
|
|
||||||
import androidx.collection.LongSparseArray
|
import androidx.collection.LongSparseArray
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
|
@ -19,20 +18,19 @@ import info.nightscout.androidaps.extensions.convertedToAbsolute
|
||||||
import info.nightscout.androidaps.extensions.iobCalc
|
import info.nightscout.androidaps.extensions.iobCalc
|
||||||
import info.nightscout.androidaps.extensions.toTemporaryBasal
|
import info.nightscout.androidaps.extensions.toTemporaryBasal
|
||||||
import info.nightscout.androidaps.interfaces.*
|
import info.nightscout.androidaps.interfaces.*
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.plugins.general.overview.OverviewData
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
|
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin
|
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
|
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
|
import info.nightscout.androidaps.workflow.CalculationWorkflow
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import io.reactivex.rxjava3.kotlin.plusAssign
|
import io.reactivex.rxjava3.kotlin.plusAssign
|
||||||
|
@ -57,12 +55,11 @@ class IobCobCalculatorPlugin @Inject constructor(
|
||||||
rh: ResourceHelper,
|
rh: ResourceHelper,
|
||||||
private val profileFunction: ProfileFunction,
|
private val profileFunction: ProfileFunction,
|
||||||
private val activePlugin: ActivePlugin,
|
private val activePlugin: ActivePlugin,
|
||||||
private val sensitivityOref1Plugin: SensitivityOref1Plugin,
|
|
||||||
private val sensitivityAAPSPlugin: SensitivityAAPSPlugin,
|
|
||||||
private val sensitivityWeightedAveragePlugin: SensitivityWeightedAveragePlugin,
|
|
||||||
private val fabricPrivacy: FabricPrivacy,
|
private val fabricPrivacy: FabricPrivacy,
|
||||||
private val dateUtil: DateUtil,
|
private val dateUtil: DateUtil,
|
||||||
private val repository: AppRepository
|
private val repository: AppRepository,
|
||||||
|
val overviewData: OverviewData,
|
||||||
|
private val calculationWorkflow: CalculationWorkflow
|
||||||
) : PluginBase(
|
) : PluginBase(
|
||||||
PluginDescription()
|
PluginDescription()
|
||||||
.mainType(PluginType.GENERAL)
|
.mainType(PluginType.GENERAL)
|
||||||
|
@ -81,7 +78,6 @@ class IobCobCalculatorPlugin @Inject constructor(
|
||||||
override var ads: AutosensDataStore = AutosensDataStore()
|
override var ads: AutosensDataStore = AutosensDataStore()
|
||||||
|
|
||||||
private val dataLock = Any()
|
private val dataLock = Any()
|
||||||
var stopCalculationTrigger = false
|
|
||||||
private var thread: Thread? = null
|
private var thread: Thread? = null
|
||||||
|
|
||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
|
@ -117,14 +113,6 @@ class IobCobCalculatorPlugin @Inject constructor(
|
||||||
resetDataAndRunCalculation("onEventPreferenceChange", event)
|
resetDataAndRunCalculation("onEventPreferenceChange", event)
|
||||||
}
|
}
|
||||||
}, fabricPrivacy::logException)
|
}, fabricPrivacy::logException)
|
||||||
// EventAppInitialized
|
|
||||||
disposable += rxBus
|
|
||||||
.toObservable(EventAppInitialized::class.java)
|
|
||||||
.observeOn(aapsSchedulers.io)
|
|
||||||
.subscribe(
|
|
||||||
{ event -> runCalculation("onEventAppInitialized", System.currentTimeMillis(), bgDataReload = true, limitDataToOldestAvailable = true, cause = event) },
|
|
||||||
fabricPrivacy::logException
|
|
||||||
)
|
|
||||||
// EventNewHistoryData
|
// EventNewHistoryData
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventNewHistoryData::class.java)
|
.toObservable(EventNewHistoryData::class.java)
|
||||||
|
@ -138,10 +126,10 @@ class IobCobCalculatorPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetDataAndRunCalculation(reason: String, event: Event?) {
|
private fun resetDataAndRunCalculation(reason: String, event: Event?) {
|
||||||
stopCalculation(reason)
|
calculationWorkflow.stopCalculation(CalculationWorkflow.MAIN_CALCULATION,reason)
|
||||||
clearCache()
|
clearCache()
|
||||||
ads.reset()
|
ads.reset()
|
||||||
runCalculation(reason, System.currentTimeMillis(), bgDataReload = false, limitDataToOldestAvailable = true, cause = event)
|
calculationWorkflow.runCalculation(CalculationWorkflow.MAIN_CALCULATION,this, overviewData, reason, System.currentTimeMillis(), bgDataReload = false, limitDataToOldestAvailable = true, cause = event, runLoop = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clearCache() {
|
override fun clearCache() {
|
||||||
|
@ -168,10 +156,9 @@ class IobCobCalculatorPlugin @Inject constructor(
|
||||||
return oldestTime
|
return oldestTime
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculateDetectionStart(from: Long, limitDataToOldestAvailable: Boolean): Long {
|
override fun calculateDetectionStart(from: Long, limitDataToOldestAvailable: Boolean): Long {
|
||||||
val profile = profileFunction.getProfile(from)
|
val profile = profileFunction.getProfile(from)
|
||||||
var dia = Constants.defaultDIA
|
val dia = profile?.dia ?: Constants.defaultDIA
|
||||||
if (profile != null) dia = profile.dia
|
|
||||||
val oldestDataAvailable = oldestDataAvailable()
|
val oldestDataAvailable = oldestDataAvailable()
|
||||||
val getBGDataFrom: Long
|
val getBGDataFrom: Long
|
||||||
if (limitDataToOldestAvailable) {
|
if (limitDataToOldestAvailable) {
|
||||||
|
@ -302,11 +289,7 @@ class IobCobCalculatorPlugin @Inject constructor(
|
||||||
override fun getMealDataWithWaitingForCalculationFinish(): MealData {
|
override fun getMealDataWithWaitingForCalculationFinish(): MealData {
|
||||||
val result = MealData()
|
val result = MealData()
|
||||||
val now = System.currentTimeMillis()
|
val now = System.currentTimeMillis()
|
||||||
val maxAbsorptionHours: Double = if (sensitivityAAPSPlugin.isEnabled() || sensitivityWeightedAveragePlugin.isEnabled()) {
|
val maxAbsorptionHours: Double = activePlugin.activeSensitivity.maxAbsorptionHours()
|
||||||
sp.getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME)
|
|
||||||
} else {
|
|
||||||
sp.getDouble(R.string.key_absorption_cutoff, Constants.DEFAULT_MAX_ABSORPTION_TIME)
|
|
||||||
}
|
|
||||||
val absorptionTimeAgo = now - (maxAbsorptionHours * T.hours(1).msecs()).toLong()
|
val absorptionTimeAgo = now - (maxAbsorptionHours * T.hours(1).msecs()).toLong()
|
||||||
repository.getCarbsDataFromTimeToTimeExpanded(absorptionTimeAgo + 1, now, true)
|
repository.getCarbsDataFromTimeToTimeExpanded(absorptionTimeAgo + 1, now, true)
|
||||||
.blockingGet()
|
.blockingGet()
|
||||||
|
@ -366,27 +349,6 @@ class IobCobCalculatorPlugin @Inject constructor(
|
||||||
return sb.toString()
|
return sb.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stopCalculation(from: String) {
|
|
||||||
if (thread?.state != Thread.State.TERMINATED) {
|
|
||||||
stopCalculationTrigger = true
|
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Stopping calculation thread: $from")
|
|
||||||
while (thread != null && thread?.state != Thread.State.TERMINATED) {
|
|
||||||
SystemClock.sleep(100)
|
|
||||||
}
|
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Calculation thread stopped: $from")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun runCalculation(from: String, end: Long, bgDataReload: Boolean, limitDataToOldestAvailable: Boolean, cause: Event?) {
|
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Starting calculation thread: " + from + " to " + dateUtil.dateAndTimeAndSecondsString(end))
|
|
||||||
if (thread == null || thread?.state == Thread.State.TERMINATED) {
|
|
||||||
thread =
|
|
||||||
if (sensitivityOref1Plugin.isEnabled()) IobCobOref1Thread(injector, this, from, end, bgDataReload, limitDataToOldestAvailable, cause)
|
|
||||||
else IobCobThread(injector, this, from, end, bgDataReload, limitDataToOldestAvailable, cause)
|
|
||||||
thread?.start()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limit rate of EventNewHistoryData
|
// Limit rate of EventNewHistoryData
|
||||||
private val historyWorker = Executors.newSingleThreadScheduledExecutor()
|
private val historyWorker = Executors.newSingleThreadScheduledExecutor()
|
||||||
private var scheduledHistoryPost: ScheduledFuture<*>? = null
|
private var scheduledHistoryPost: ScheduledFuture<*>? = null
|
||||||
|
@ -428,7 +390,7 @@ class IobCobCalculatorPlugin @Inject constructor(
|
||||||
// When historical data is changed (coming from NS etc) finished calculations after this date must be invalidated
|
// When historical data is changed (coming from NS etc) finished calculations after this date must be invalidated
|
||||||
private fun newHistoryData(oldDataTimestamp: Long, bgDataReload: Boolean, event: Event) {
|
private fun newHistoryData(oldDataTimestamp: Long, bgDataReload: Boolean, event: Event) {
|
||||||
//log.debug("Locking onNewHistoryData");
|
//log.debug("Locking onNewHistoryData");
|
||||||
stopCalculation("onEventNewHistoryData")
|
calculationWorkflow.stopCalculation(CalculationWorkflow.MAIN_CALCULATION,"onEventNewHistoryData")
|
||||||
synchronized(dataLock) {
|
synchronized(dataLock) {
|
||||||
|
|
||||||
// clear up 5 min back for proper COB calculation
|
// clear up 5 min back for proper COB calculation
|
||||||
|
@ -452,7 +414,7 @@ class IobCobCalculatorPlugin @Inject constructor(
|
||||||
}
|
}
|
||||||
ads.newHistoryData(time, aapsLogger, dateUtil)
|
ads.newHistoryData(time, aapsLogger, dateUtil)
|
||||||
}
|
}
|
||||||
runCalculation(event.javaClass.simpleName, System.currentTimeMillis(), bgDataReload, true, event)
|
calculationWorkflow.runCalculation(CalculationWorkflow.MAIN_CALCULATION,this, overviewData, event.javaClass.simpleName, System.currentTimeMillis(), bgDataReload, true, event, runLoop = true)
|
||||||
//log.debug("Releasing onNewHistoryData");
|
//log.debug("Releasing onNewHistoryData");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,17 +536,17 @@ class IobCobCalculatorPlugin @Inject constructor(
|
||||||
override fun getTempBasalIncludingConvertedExtended(timestamp: Long): TemporaryBasal? {
|
override fun getTempBasalIncludingConvertedExtended(timestamp: Long): TemporaryBasal? {
|
||||||
val tb = repository.getTemporaryBasalActiveAt(timestamp).blockingGet()
|
val tb = repository.getTemporaryBasalActiveAt(timestamp).blockingGet()
|
||||||
if (tb is ValueWrapper.Existing) return tb.value
|
if (tb is ValueWrapper.Existing) return tb.value
|
||||||
return getConvertedExtended(timestamp);
|
return getConvertedExtended(timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTempBasalIncludingConvertedExtendedForRange(startTime: Long, endTime: Long, calculationStep: Long): Map<Long, TemporaryBasal?> {
|
override fun getTempBasalIncludingConvertedExtendedForRange(startTime: Long, endTime: Long, calculationStep: Long): Map<Long, TemporaryBasal?> {
|
||||||
val tempBasals = HashMap<Long, TemporaryBasal?>();
|
val tempBasals = HashMap<Long, TemporaryBasal?>()
|
||||||
val tbs = repository.getTemporaryBasalsDataActiveBetweenTimeAndTime(startTime, endTime).blockingGet()
|
val tbs = repository.getTemporaryBasalsDataActiveBetweenTimeAndTime(startTime, endTime).blockingGet()
|
||||||
for (t in startTime until endTime step calculationStep) {
|
for (t in startTime until endTime step calculationStep) {
|
||||||
val tb = tbs.firstOrNull { basal -> basal.timestamp <= t && (basal.timestamp + basal.duration) > t }
|
val tb = tbs.firstOrNull { basal -> basal.timestamp <= t && (basal.timestamp + basal.duration) > t }
|
||||||
tempBasals[t] = tb ?: getConvertedExtended(t)
|
tempBasals[t] = tb ?: getConvertedExtended(t)
|
||||||
}
|
}
|
||||||
return tempBasals;
|
return tempBasals
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun calculateAbsoluteIobFromBaseBasals(toTime: Long): IobTotal {
|
override fun calculateAbsoluteIobFromBaseBasals(toTime: Long): IobTotal {
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
package info.nightscout.androidaps.plugins.iob.iobCobCalculator
|
package info.nightscout.androidaps.plugins.iob.iobCobCalculator
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.PowerManager
|
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
|
import androidx.work.Worker
|
||||||
|
import androidx.work.WorkerParameters
|
||||||
|
import androidx.work.workDataOf
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
@ -12,9 +14,8 @@ import info.nightscout.androidaps.events.Event
|
||||||
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
||||||
import info.nightscout.androidaps.extensions.target
|
import info.nightscout.androidaps.extensions.target
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
|
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
|
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
||||||
|
@ -23,6 +24,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
|
||||||
|
import info.nightscout.androidaps.receivers.DataWorker
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
|
@ -30,6 +32,9 @@ import info.nightscout.androidaps.utils.Profiler
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.workflow.CalculationWorkflow
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -38,15 +43,10 @@ import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.roundToLong
|
import kotlin.math.roundToLong
|
||||||
|
|
||||||
class IobCobOref1Thread internal constructor(
|
class IobCobOref1Worker(
|
||||||
private val injector: HasAndroidInjector,
|
context: Context,
|
||||||
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, // cannot be injected : HistoryBrowser uses different instance
|
params: WorkerParameters
|
||||||
private val from: String,
|
) : Worker(context, params) {
|
||||||
private val end: Long,
|
|
||||||
private val bgDataReload: Boolean,
|
|
||||||
private val limitDataToOldestAvailable: Boolean,
|
|
||||||
private val cause: Event?
|
|
||||||
) : Thread() {
|
|
||||||
|
|
||||||
@Inject lateinit var aapsLogger: AAPSLogger
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
@Inject lateinit var sp: SP
|
@Inject lateinit var sp: SP
|
||||||
|
@ -62,48 +62,53 @@ class IobCobOref1Thread internal constructor(
|
||||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
|
@Inject lateinit var dataWorker: DataWorker
|
||||||
private var mWakeLock: PowerManager.WakeLock? = null
|
@Inject lateinit var calculationWorkflow: CalculationWorkflow
|
||||||
|
|
||||||
init {
|
init {
|
||||||
injector.androidInjector().inject(this)
|
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||||
mWakeLock = (context.applicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, rh.gs(R.string.app_name) + ":iobCobThread")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun run() {
|
class IobCobOref1WorkerData(
|
||||||
|
val injector: HasAndroidInjector,
|
||||||
|
val iobCobCalculator: IobCobCalculator, // cannot be injected : HistoryBrowser uses different instance
|
||||||
|
val from: String,
|
||||||
|
val end: Long,
|
||||||
|
val limitDataToOldestAvailable: Boolean,
|
||||||
|
val cause: Event?
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun doWork(): Result {
|
||||||
|
|
||||||
|
val data = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as IobCobOref1WorkerData?
|
||||||
|
?: return Result.failure(workDataOf("Error" to "missing input data"))
|
||||||
|
|
||||||
val start = dateUtil.now()
|
val start = dateUtil.now()
|
||||||
mWakeLock?.acquire(T.mins(10).msecs())
|
|
||||||
try {
|
try {
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread started: $from")
|
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread started: ${data.from}")
|
||||||
if (!profileFunction.isProfileValid("IobCobThread")) {
|
if (!profileFunction.isProfileValid("IobCobThread")) {
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No profile): $from")
|
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No profile): ${data.from}")
|
||||||
return // app still initializing
|
return Result.failure(workDataOf("Error" to "app still initializing"))
|
||||||
}
|
}
|
||||||
//log.debug("Locking calculateSensitivityData");
|
//log.debug("Locking calculateSensitivityData");
|
||||||
val oldestTimeWithData = iobCobCalculatorPlugin.calculateDetectionStart(end, limitDataToOldestAvailable)
|
val oldestTimeWithData = data.iobCobCalculator.calculateDetectionStart(data.end, data.limitDataToOldestAvailable)
|
||||||
if (bgDataReload) {
|
|
||||||
iobCobCalculatorPlugin.ads.loadBgData(end, repository, aapsLogger, dateUtil, rxBus)
|
|
||||||
iobCobCalculatorPlugin.clearCache()
|
|
||||||
}
|
|
||||||
// work on local copy and set back when finished
|
// work on local copy and set back when finished
|
||||||
val ads = iobCobCalculatorPlugin.ads.clone()
|
val ads = data.iobCobCalculator.ads.clone()
|
||||||
val bucketedData = ads.bucketedData
|
val bucketedData = ads.bucketedData
|
||||||
val autosensDataTable = ads.autosensDataTable
|
val autosensDataTable = ads.autosensDataTable
|
||||||
if (bucketedData == null || bucketedData.size < 3) {
|
if (bucketedData == null || bucketedData.size < 3) {
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No bucketed data available): $from")
|
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No bucketed data available): ${data.from}")
|
||||||
return
|
return Result.failure(workDataOf("Error" to "Aborting calculation thread (No bucketed data available): ${data.from}"))
|
||||||
}
|
}
|
||||||
val prevDataTime = ads.roundUpTime(bucketedData[bucketedData.size - 3].timestamp)
|
val prevDataTime = ads.roundUpTime(bucketedData[bucketedData.size - 3].timestamp)
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Prev data time: " + dateUtil.dateAndTimeString(prevDataTime))
|
aapsLogger.debug(LTag.AUTOSENS, "Prev data time: " + dateUtil.dateAndTimeString(prevDataTime))
|
||||||
var previous = autosensDataTable[prevDataTime]
|
var previous = autosensDataTable[prevDataTime]
|
||||||
// start from oldest to be able sub cob
|
// start from oldest to be able sub cob
|
||||||
for (i in bucketedData.size - 4 downTo 0) {
|
for (i in bucketedData.size - 4 downTo 0) {
|
||||||
val progress = i.toString() + if (buildHelper.isDev()) " ($from)" else ""
|
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.IOB_COB_OREF, 100 - (100.0 * i / bucketedData.size).toInt(), data.cause))
|
||||||
rxBus.send(EventIobCalculationProgress(progress, cause))
|
if (isStopped) {
|
||||||
if (iobCobCalculatorPlugin.stopCalculationTrigger) {
|
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): ${data.from}")
|
||||||
iobCobCalculatorPlugin.stopCalculationTrigger = false
|
return Result.failure(workDataOf("Error" to "Aborting calculation thread (trigger): ${data.from}"))
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): $from")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
// check if data already exists
|
// check if data already exists
|
||||||
var bgTime = bucketedData[i].timestamp
|
var bgTime = bucketedData[i].timestamp
|
||||||
|
@ -116,12 +121,12 @@ class IobCobOref1Thread internal constructor(
|
||||||
}
|
}
|
||||||
val profile = profileFunction.getProfile(bgTime)
|
val profile = profileFunction.getProfile(bgTime)
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (no profile): $from")
|
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (no profile): ${data.from}")
|
||||||
continue // profile not set yet
|
continue // profile not set yet
|
||||||
}
|
}
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Processing calculation thread: " + from + " (" + i + "/" + bucketedData.size + ")")
|
aapsLogger.debug(LTag.AUTOSENS, "Processing calculation thread: ${data.from} ($i/${bucketedData.size})")
|
||||||
val sens = profile.getIsfMgdl(bgTime)
|
val sens = profile.getIsfMgdl(bgTime)
|
||||||
val autosensData = AutosensData(injector)
|
val autosensData = AutosensData(data.injector)
|
||||||
autosensData.time = bgTime
|
autosensData.time = bgTime
|
||||||
if (previous != null) autosensData.activeCarbsList = previous.cloneCarbsList() else autosensData.activeCarbsList = ArrayList()
|
if (previous != null) autosensData.activeCarbsList = previous.cloneCarbsList() else autosensData.activeCarbsList = ArrayList()
|
||||||
|
|
||||||
|
@ -136,7 +141,7 @@ class IobCobOref1Thread internal constructor(
|
||||||
autosensData.bg = bg
|
autosensData.bg = bg
|
||||||
delta = bg - bucketedData[i + 1].value
|
delta = bg - bucketedData[i + 1].value
|
||||||
avgDelta = (bg - bucketedData[i + 3].value) / 3
|
avgDelta = (bg - bucketedData[i + 3].value) / 3
|
||||||
val iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime, profile)
|
val iob = data.iobCobCalculator.calculateFromTreatmentsAndTemps(bgTime, profile)
|
||||||
val bgi = -iob.activity * sens * 5
|
val bgi = -iob.activity * sens * 5
|
||||||
val deviation = delta - bgi
|
val deviation = delta - bgi
|
||||||
val avgDeviation = ((avgDelta - bgi) * 1000).roundToLong() / 1000.0
|
val avgDeviation = ((avgDelta - bgi) * 1000).roundToLong() / 1000.0
|
||||||
|
@ -312,22 +317,27 @@ class IobCobOref1Thread internal constructor(
|
||||||
if (min in 0..4 && hours % 2 == 0) autosensData.extraDeviation.add(0.0)
|
if (min in 0..4 && hours % 2 == 0) autosensData.extraDeviation.add(0.0)
|
||||||
previous = autosensData
|
previous = autosensData
|
||||||
if (bgTime < dateUtil.now()) autosensDataTable.put(bgTime, autosensData)
|
if (bgTime < dateUtil.now()) autosensDataTable.put(bgTime, autosensData)
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Running detectSensitivity from: " + dateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + dateUtil.dateAndTimeString(bgTime) + " lastDataTime:" + ads.lastDataTime(dateUtil))
|
aapsLogger.debug(
|
||||||
|
LTag.AUTOSENS,
|
||||||
|
"Running detectSensitivity from: " + dateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + dateUtil.dateAndTimeString(bgTime) + " lastDataTime:" + ads.lastDataTime(
|
||||||
|
dateUtil
|
||||||
|
)
|
||||||
|
)
|
||||||
val sensitivity = activePlugin.activeSensitivity.detectSensitivity(ads, oldestTimeWithData, bgTime)
|
val sensitivity = activePlugin.activeSensitivity.detectSensitivity(ads, oldestTimeWithData, bgTime)
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Sensitivity result: $sensitivity")
|
aapsLogger.debug(LTag.AUTOSENS, "Sensitivity result: $sensitivity")
|
||||||
autosensData.autosensResult = sensitivity
|
autosensData.autosensResult = sensitivity
|
||||||
aapsLogger.debug(LTag.AUTOSENS, autosensData.toString())
|
aapsLogger.debug(LTag.AUTOSENS, autosensData.toString())
|
||||||
}
|
}
|
||||||
iobCobCalculatorPlugin.ads = ads
|
data.iobCobCalculator.ads = ads
|
||||||
Thread {
|
Thread {
|
||||||
SystemClock.sleep(1000)
|
SystemClock.sleep(1000)
|
||||||
rxBus.send(EventAutosensCalculationFinished(cause))
|
rxBus.send(EventAutosensCalculationFinished(data.cause))
|
||||||
}.start()
|
}.start()
|
||||||
} finally {
|
} finally {
|
||||||
mWakeLock?.release()
|
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.IOB_COB_OREF, 100, data.cause))
|
||||||
rxBus.send(EventIobCalculationProgress("", cause))
|
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: ${data.from}")
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: $from")
|
|
||||||
profiler.log(LTag.AUTOSENS, "IobCobOref1Thread", start)
|
profiler.log(LTag.AUTOSENS, "IobCobOref1Thread", start)
|
||||||
}
|
}
|
||||||
|
return Result.success()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
package info.nightscout.androidaps.plugins.iob.iobCobCalculator
|
package info.nightscout.androidaps.plugins.iob.iobCobCalculator
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.PowerManager
|
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
|
import androidx.work.Worker
|
||||||
|
import androidx.work.WorkerParameters
|
||||||
|
import androidx.work.workDataOf
|
||||||
import dagger.android.HasAndroidInjector
|
import dagger.android.HasAndroidInjector
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
@ -10,9 +12,8 @@ import info.nightscout.androidaps.database.AppRepository
|
||||||
import info.nightscout.androidaps.events.Event
|
import info.nightscout.androidaps.events.Event
|
||||||
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
import info.nightscout.androidaps.events.EventAutosensCalculationFinished
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
|
import info.nightscout.androidaps.interfaces.IobCobCalculator
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.shared.logging.AAPSLogger
|
|
||||||
import info.nightscout.shared.logging.LTag
|
|
||||||
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
|
import info.nightscout.androidaps.plugins.aps.openAPSSMB.SMBDefaults
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
|
||||||
|
@ -21,6 +22,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.data.AutosensData
|
||||||
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCalculationProgress
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin
|
||||||
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
|
import info.nightscout.androidaps.plugins.sensitivity.SensitivityWeightedAveragePlugin
|
||||||
|
import info.nightscout.androidaps.receivers.DataWorker
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.DecimalFormatter
|
import info.nightscout.androidaps.utils.DecimalFormatter
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
|
@ -28,23 +30,20 @@ import info.nightscout.androidaps.utils.Profiler
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
import info.nightscout.androidaps.utils.buildHelper.BuildHelper
|
||||||
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
import info.nightscout.androidaps.utils.resources.ResourceHelper
|
||||||
|
import info.nightscout.androidaps.workflow.CalculationWorkflow
|
||||||
|
import info.nightscout.shared.logging.AAPSLogger
|
||||||
|
import info.nightscout.shared.logging.LTag
|
||||||
import info.nightscout.shared.sharedPreferences.SP
|
import info.nightscout.shared.sharedPreferences.SP
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.roundToLong
|
import kotlin.math.roundToLong
|
||||||
|
|
||||||
class IobCobThread @Inject internal constructor(
|
class IobCobOrefWorker @Inject internal constructor(
|
||||||
private val injector: HasAndroidInjector,
|
context: Context,
|
||||||
private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, // cannot be injected : HistoryBrowser uses different instance
|
params: WorkerParameters
|
||||||
private val from: String,
|
) : Worker(context, params) {
|
||||||
private val end: Long,
|
|
||||||
private val bgDataReload: Boolean,
|
|
||||||
private val limitDataToOldestAvailable: Boolean,
|
|
||||||
private val cause: Event?
|
|
||||||
) : Thread() {
|
|
||||||
|
|
||||||
@Inject lateinit var aapsLogger: AAPSLogger
|
@Inject lateinit var aapsLogger: AAPSLogger
|
||||||
@Inject lateinit var sp: SP
|
@Inject lateinit var sp: SP
|
||||||
|
@ -60,48 +59,51 @@ class IobCobThread @Inject internal constructor(
|
||||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
@Inject lateinit var repository: AppRepository
|
@Inject lateinit var repository: AppRepository
|
||||||
|
@Inject lateinit var dataWorker: DataWorker
|
||||||
private var mWakeLock: PowerManager.WakeLock? = null
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
injector.androidInjector().inject(this)
|
(context.applicationContext as HasAndroidInjector).androidInjector().inject(this)
|
||||||
mWakeLock = (context.applicationContext.getSystemService(Context.POWER_SERVICE) as PowerManager).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, rh.gs(R.string.app_name) + ":iobCobThread")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun run() {
|
class IobCobOrefWorkerData(
|
||||||
|
val injector: HasAndroidInjector,
|
||||||
|
val iobCobCalculatorPlugin: IobCobCalculator, // cannot be injected : HistoryBrowser uses different instance
|
||||||
|
val from: String,
|
||||||
|
val end: Long,
|
||||||
|
val limitDataToOldestAvailable: Boolean,
|
||||||
|
val cause: Event?
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun doWork(): Result {
|
||||||
|
val data = dataWorker.pickupObject(inputData.getLong(DataWorker.STORE_KEY, -1)) as IobCobOrefWorkerData?
|
||||||
|
?: return Result.failure(workDataOf("Error" to "missing input data"))
|
||||||
|
|
||||||
val start = dateUtil.now()
|
val start = dateUtil.now()
|
||||||
mWakeLock?.acquire(T.mins(10).msecs())
|
|
||||||
try {
|
try {
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread started: $from")
|
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread started: ${data.from}")
|
||||||
if (!profileFunction.isProfileValid("IobCobThread")) {
|
if (!profileFunction.isProfileValid("IobCobThread")) {
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No profile): $from")
|
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No profile): ${data.from}")
|
||||||
return // app still initializing
|
return Result.failure(workDataOf("Error" to "app still initializing"))
|
||||||
}
|
}
|
||||||
//log.debug("Locking calculateSensitivityData");
|
//log.debug("Locking calculateSensitivityData");
|
||||||
val oldestTimeWithData = iobCobCalculatorPlugin.calculateDetectionStart(end, limitDataToOldestAvailable)
|
val oldestTimeWithData = data.iobCobCalculatorPlugin.calculateDetectionStart(data.end, data.limitDataToOldestAvailable)
|
||||||
if (bgDataReload) {
|
|
||||||
iobCobCalculatorPlugin.ads.loadBgData(end, repository, aapsLogger, dateUtil, rxBus)
|
|
||||||
iobCobCalculatorPlugin.clearCache()
|
|
||||||
}
|
|
||||||
// work on local copy and set back when finished
|
// work on local copy and set back when finished
|
||||||
val ads = iobCobCalculatorPlugin.ads.clone()
|
val ads = data.iobCobCalculatorPlugin.ads.clone()
|
||||||
val bucketedData = ads.bucketedData
|
val bucketedData = ads.bucketedData
|
||||||
val autosensDataTable = ads.autosensDataTable
|
val autosensDataTable = ads.autosensDataTable
|
||||||
if (bucketedData == null || bucketedData.size < 3) {
|
if (bucketedData == null || bucketedData.size < 3) {
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No bucketed data available): $from")
|
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (No bucketed data available): ${data.from}")
|
||||||
return
|
return Result.failure(workDataOf("Error" to "Aborting calculation thread (No bucketed data available): ${data.from}"))
|
||||||
}
|
}
|
||||||
val prevDataTime = ads.roundUpTime(bucketedData[bucketedData.size - 3].timestamp)
|
val prevDataTime = ads.roundUpTime(bucketedData[bucketedData.size - 3].timestamp)
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Prev data time: " + dateUtil.dateAndTimeString(prevDataTime))
|
aapsLogger.debug(LTag.AUTOSENS, "Prev data time: " + dateUtil.dateAndTimeString(prevDataTime))
|
||||||
var previous = autosensDataTable[prevDataTime]
|
var previous = autosensDataTable[prevDataTime]
|
||||||
// start from oldest to be able sub cob
|
// start from oldest to be able sub cob
|
||||||
for (i in bucketedData.size - 4 downTo 0) {
|
for (i in bucketedData.size - 4 downTo 0) {
|
||||||
val progress = i.toString() + if (buildHelper.isDev()) " ($from)" else ""
|
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.IOB_COB_OREF, 100 - (100.0 * i / bucketedData.size).toInt(), data.cause))
|
||||||
rxBus.send(EventIobCalculationProgress(progress, cause))
|
if (isStopped) {
|
||||||
if (iobCobCalculatorPlugin.stopCalculationTrigger) {
|
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): ${data.from}")
|
||||||
iobCobCalculatorPlugin.stopCalculationTrigger = false
|
return Result.failure(workDataOf("Error" to "Aborting calculation thread (trigger): ${data.from}"))
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (trigger): $from")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
// check if data already exists
|
// check if data already exists
|
||||||
var bgTime = bucketedData[i].timestamp
|
var bgTime = bucketedData[i].timestamp
|
||||||
|
@ -114,12 +116,12 @@ class IobCobThread @Inject internal constructor(
|
||||||
}
|
}
|
||||||
val profile = profileFunction.getProfile(bgTime)
|
val profile = profileFunction.getProfile(bgTime)
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (no profile): $from")
|
aapsLogger.debug(LTag.AUTOSENS, "Aborting calculation thread (no profile): ${data.from}")
|
||||||
continue // profile not set yet
|
continue // profile not set yet
|
||||||
}
|
}
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Processing calculation thread: " + from + " (" + i + "/" + bucketedData.size + ")")
|
aapsLogger.debug(LTag.AUTOSENS, "Processing calculation thread: ${data.from} ($i/${bucketedData.size})")
|
||||||
val sens = profile.getIsfMgdl(bgTime)
|
val sens = profile.getIsfMgdl(bgTime)
|
||||||
val autosensData = AutosensData(injector)
|
val autosensData = AutosensData(data.injector)
|
||||||
autosensData.time = bgTime
|
autosensData.time = bgTime
|
||||||
if (previous != null) autosensData.activeCarbsList = previous.cloneCarbsList() else autosensData.activeCarbsList = ArrayList()
|
if (previous != null) autosensData.activeCarbsList = previous.cloneCarbsList() else autosensData.activeCarbsList = ArrayList()
|
||||||
|
|
||||||
|
@ -134,7 +136,7 @@ class IobCobThread @Inject internal constructor(
|
||||||
autosensData.bg = bg
|
autosensData.bg = bg
|
||||||
delta = bg - bucketedData[i + 1].value
|
delta = bg - bucketedData[i + 1].value
|
||||||
avgDelta = (bg - bucketedData[i + 3].value) / 3
|
avgDelta = (bg - bucketedData[i + 3].value) / 3
|
||||||
val iob = iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime, profile)
|
val iob = data.iobCobCalculatorPlugin.calculateFromTreatmentsAndTemps(bgTime, profile)
|
||||||
val bgi = -iob.activity * sens * 5
|
val bgi = -iob.activity * sens * 5
|
||||||
val deviation = delta - bgi
|
val deviation = delta - bgi
|
||||||
val avgDeviation = ((avgDelta - bgi) * 1000).roundToLong() / 1000.0
|
val avgDeviation = ((avgDelta - bgi) * 1000).roundToLong() / 1000.0
|
||||||
|
@ -158,7 +160,7 @@ class IobCobThread @Inject internal constructor(
|
||||||
if (ad == null) {
|
if (ad == null) {
|
||||||
aapsLogger.debug(LTag.AUTOSENS, autosensDataTable.toString())
|
aapsLogger.debug(LTag.AUTOSENS, autosensDataTable.toString())
|
||||||
aapsLogger.debug(LTag.AUTOSENS, bucketedData.toString())
|
aapsLogger.debug(LTag.AUTOSENS, bucketedData.toString())
|
||||||
//aapsLogger.debug(LTag.AUTOSENS, iobCobCalculatorPlugin.getBgReadingsDataTable().toString())
|
//aapsLogger.debug(LTag.AUTOSENS, data.iobCobCalculatorPlugin.getBgReadingsDataTable().toString())
|
||||||
val notification = Notification(Notification.SEND_LOGFILES, rh.gs(R.string.sendlogfiles), Notification.LOW)
|
val notification = Notification(Notification.SEND_LOGFILES, rh.gs(R.string.sendlogfiles), Notification.LOW)
|
||||||
rxBus.send(EventNewNotification(notification))
|
rxBus.send(EventNewNotification(notification))
|
||||||
sp.putBoolean("log_AUTOSENS", true)
|
sp.putBoolean("log_AUTOSENS", true)
|
||||||
|
@ -181,7 +183,7 @@ class IobCobThread @Inject internal constructor(
|
||||||
fabricPrivacy.logException(e)
|
fabricPrivacy.logException(e)
|
||||||
aapsLogger.debug(autosensDataTable.toString())
|
aapsLogger.debug(autosensDataTable.toString())
|
||||||
aapsLogger.debug(bucketedData.toString())
|
aapsLogger.debug(bucketedData.toString())
|
||||||
//aapsLogger.debug(iobCobCalculatorPlugin.getBgReadingsDataTable().toString())
|
//aapsLogger.debug(data.iobCobCalculatorPlugin.getBgReadingsDataTable().toString())
|
||||||
val notification = Notification(Notification.SEND_LOGFILES, rh.gs(R.string.sendlogfiles), Notification.LOW)
|
val notification = Notification(Notification.SEND_LOGFILES, rh.gs(R.string.sendlogfiles), Notification.LOW)
|
||||||
rxBus.send(EventNewNotification(notification))
|
rxBus.send(EventNewNotification(notification))
|
||||||
sp.putBoolean("log_AUTOSENS", true)
|
sp.putBoolean("log_AUTOSENS", true)
|
||||||
|
@ -258,22 +260,27 @@ class IobCobThread @Inject internal constructor(
|
||||||
}
|
}
|
||||||
previous = autosensData
|
previous = autosensData
|
||||||
if (bgTime < dateUtil.now()) autosensDataTable.put(bgTime, autosensData)
|
if (bgTime < dateUtil.now()) autosensDataTable.put(bgTime, autosensData)
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Running detectSensitivity from: " + dateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + dateUtil.dateAndTimeString(bgTime) + " lastDataTime:" + ads.lastDataTime(dateUtil))
|
aapsLogger.debug(
|
||||||
|
LTag.AUTOSENS,
|
||||||
|
"Running detectSensitivity from: " + dateUtil.dateAndTimeString(oldestTimeWithData) + " to: " + dateUtil.dateAndTimeString(bgTime) + " lastDataTime:" + ads.lastDataTime(
|
||||||
|
dateUtil
|
||||||
|
)
|
||||||
|
)
|
||||||
val sensitivity = activePlugin.activeSensitivity.detectSensitivity(ads, oldestTimeWithData, bgTime)
|
val sensitivity = activePlugin.activeSensitivity.detectSensitivity(ads, oldestTimeWithData, bgTime)
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "Sensitivity result: $sensitivity")
|
aapsLogger.debug(LTag.AUTOSENS, "Sensitivity result: $sensitivity")
|
||||||
autosensData.autosensResult = sensitivity
|
autosensData.autosensResult = sensitivity
|
||||||
aapsLogger.debug(LTag.AUTOSENS, autosensData.toString())
|
aapsLogger.debug(LTag.AUTOSENS, autosensData.toString())
|
||||||
}
|
}
|
||||||
iobCobCalculatorPlugin.ads = ads
|
data.iobCobCalculatorPlugin.ads = ads
|
||||||
Thread {
|
Thread {
|
||||||
SystemClock.sleep(1000)
|
SystemClock.sleep(1000)
|
||||||
rxBus.send(EventAutosensCalculationFinished(cause))
|
rxBus.send(EventAutosensCalculationFinished(data.cause))
|
||||||
}.start()
|
}.start()
|
||||||
} finally {
|
} finally {
|
||||||
mWakeLock?.release()
|
rxBus.send(EventIobCalculationProgress(CalculationWorkflow.ProgressData.IOB_COB_OREF, 100, data.cause))
|
||||||
rxBus.send(EventIobCalculationProgress("", cause))
|
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: ${data.from}")
|
||||||
aapsLogger.debug(LTag.AUTOSENS, "AUTOSENSDATA thread ended: $from")
|
|
||||||
profiler.log(LTag.AUTOSENS, "IobCobThread", start)
|
profiler.log(LTag.AUTOSENS, "IobCobThread", start)
|
||||||
}
|
}
|
||||||
|
return Result.success()
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package info.nightscout.androidaps.plugins.iob.iobCobCalculator.events
|
package info.nightscout.androidaps.plugins.iob.iobCobCalculator.events
|
||||||
|
|
||||||
import info.nightscout.androidaps.events.Event
|
import info.nightscout.androidaps.events.Event
|
||||||
|
import info.nightscout.androidaps.workflow.CalculationWorkflow
|
||||||
|
|
||||||
class EventIobCalculationProgress(val progress: String, val cause: Event?) : Event()
|
class EventIobCalculationProgress(val pass: CalculationWorkflow.ProgressData, val progressPct: Int, val cause: Event?) : Event()
|
|
@ -9,15 +9,18 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.AdapterView
|
import android.widget.AdapterView
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
|
import com.google.android.material.tabs.TabLayout
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
import info.nightscout.androidaps.Constants
|
import info.nightscout.androidaps.Constants
|
||||||
import info.nightscout.androidaps.R
|
import info.nightscout.androidaps.R
|
||||||
|
import info.nightscout.androidaps.activities.SingleFragmentActivity
|
||||||
import info.nightscout.androidaps.data.ProfileSealed
|
import info.nightscout.androidaps.data.ProfileSealed
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
import info.nightscout.androidaps.database.entities.UserEntry.Action
|
||||||
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
import info.nightscout.androidaps.database.entities.UserEntry.Sources
|
||||||
import info.nightscout.androidaps.database.entities.ValueWithUnit
|
import info.nightscout.androidaps.database.entities.ValueWithUnit
|
||||||
import info.nightscout.androidaps.databinding.LocalprofileFragmentBinding
|
import info.nightscout.androidaps.databinding.LocalprofileFragmentBinding
|
||||||
import info.nightscout.androidaps.dialogs.ProfileSwitchDialog
|
import info.nightscout.androidaps.dialogs.ProfileSwitchDialog
|
||||||
|
import info.nightscout.androidaps.extensions.toVisibility
|
||||||
import info.nightscout.androidaps.interfaces.ActivePlugin
|
import info.nightscout.androidaps.interfaces.ActivePlugin
|
||||||
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
import info.nightscout.androidaps.interfaces.GlucoseUnit
|
||||||
import info.nightscout.androidaps.interfaces.Profile
|
import info.nightscout.androidaps.interfaces.Profile
|
||||||
|
@ -29,6 +32,7 @@ import info.nightscout.androidaps.utils.DecimalFormatter
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.HardLimits
|
import info.nightscout.androidaps.utils.HardLimits
|
||||||
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
import info.nightscout.androidaps.utils.alertDialogs.OKDialog
|
||||||
|
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.rx.AapsSchedulers
|
import info.nightscout.androidaps.utils.rx.AapsSchedulers
|
||||||
import info.nightscout.androidaps.utils.ui.TimeListEdit
|
import info.nightscout.androidaps.utils.ui.TimeListEdit
|
||||||
|
@ -49,14 +53,15 @@ class LocalProfileFragment : DaggerFragment() {
|
||||||
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
@Inject lateinit var fabricPrivacy: FabricPrivacy
|
||||||
@Inject lateinit var localProfilePlugin: LocalProfilePlugin
|
@Inject lateinit var localProfilePlugin: LocalProfilePlugin
|
||||||
@Inject lateinit var hardLimits: HardLimits
|
@Inject lateinit var hardLimits: HardLimits
|
||||||
|
@Inject lateinit var protectionCheck: ProtectionCheck
|
||||||
@Inject lateinit var dateUtil: DateUtil
|
@Inject lateinit var dateUtil: DateUtil
|
||||||
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
@Inject lateinit var aapsSchedulers: AapsSchedulers
|
||||||
@Inject lateinit var uel: UserEntryLogger
|
@Inject lateinit var uel: UserEntryLogger
|
||||||
|
|
||||||
private var disposable: CompositeDisposable = CompositeDisposable()
|
private var disposable: CompositeDisposable = CompositeDisposable()
|
||||||
|
private var inMenu = false
|
||||||
|
private var queryingProtection = false
|
||||||
private var basalView: TimeListEdit? = null
|
private var basalView: TimeListEdit? = null
|
||||||
// private var spinner: SpinnerHelper? = null
|
|
||||||
|
|
||||||
private val save = Runnable {
|
private val save = Runnable {
|
||||||
doEdit()
|
doEdit()
|
||||||
|
@ -88,8 +93,7 @@ class LocalProfileFragment : DaggerFragment() {
|
||||||
|
|
||||||
private var _binding: LocalprofileFragmentBinding? = null
|
private var _binding: LocalprofileFragmentBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
|
@ -99,31 +103,20 @@ class LocalProfileFragment : DaggerFragment() {
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
// activate DIA tab
|
val parentClass = this.activity?.let { it::class.java }
|
||||||
processVisibilityOnClick(binding.diaTab)
|
inMenu = parentClass == SingleFragmentActivity::class.java
|
||||||
binding.diaPlaceholder.visibility = View.VISIBLE
|
updateProtectedUi()
|
||||||
// setup listeners
|
processVisibility(0)
|
||||||
binding.diaTab.setOnClickListener {
|
binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||||
processVisibilityOnClick(it)
|
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||||
binding.diaPlaceholder.visibility = View.VISIBLE
|
processVisibility(tab.position)
|
||||||
}
|
}
|
||||||
binding.icTab.setOnClickListener {
|
|
||||||
processVisibilityOnClick(it)
|
override fun onTabUnselected(tab: TabLayout.Tab) {}
|
||||||
binding.ic.visibility = View.VISIBLE
|
override fun onTabReselected(tab: TabLayout.Tab) {}
|
||||||
}
|
})
|
||||||
binding.isfTab.setOnClickListener {
|
binding.diaLabel.labelFor = binding.dia.editTextId
|
||||||
processVisibilityOnClick(it)
|
binding.unlock.setOnClickListener { queryProtection() }
|
||||||
binding.isf.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
binding.basalTab.setOnClickListener {
|
|
||||||
processVisibilityOnClick(it)
|
|
||||||
binding.basal.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
binding.targetTab.setOnClickListener {
|
|
||||||
processVisibilityOnClick(it)
|
|
||||||
binding.target.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
binding.dia.editText?.id?.let { binding.diaLabel.labelFor = it }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun build() {
|
fun build() {
|
||||||
|
@ -222,7 +215,6 @@ class LocalProfileFragment : DaggerFragment() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spinner
|
|
||||||
context?.let { context ->
|
context?.let { context ->
|
||||||
val profileList: ArrayList<CharSequence> = localProfilePlugin.profile?.getProfileList() ?: ArrayList()
|
val profileList: ArrayList<CharSequence> = localProfilePlugin.profile?.getProfileList() ?: ArrayList()
|
||||||
binding.profileList.setAdapter(ArrayAdapter(context, R.layout.spinner_centered, profileList))
|
binding.profileList.setAdapter(ArrayAdapter(context, R.layout.spinner_centered, profileList))
|
||||||
|
@ -301,7 +293,7 @@ class LocalProfileFragment : DaggerFragment() {
|
||||||
|
|
||||||
binding.profileswitch.setOnClickListener {
|
binding.profileswitch.setOnClickListener {
|
||||||
ProfileSwitchDialog()
|
ProfileSwitchDialog()
|
||||||
.also { it.arguments = Bundle().also { bundle -> bundle.putInt("profileIndex", localProfilePlugin.currentProfileIndex) } }
|
.also { it.arguments = Bundle().also { bundle -> bundle.putString("profileName", localProfilePlugin.currentProfile()?.name) } }
|
||||||
.show(childFragmentManager, "ProfileSwitchDialog")
|
.show(childFragmentManager, "ProfileSwitchDialog")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,6 +321,7 @@ class LocalProfileFragment : DaggerFragment() {
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
if (inMenu) queryProtection() else updateProtectedUi()
|
||||||
disposable += rxBus
|
disposable += rxBus
|
||||||
.toObservable(EventLocalProfileChanged::class.java)
|
.toObservable(EventLocalProfileChanged::class.java)
|
||||||
.observeOn(aapsSchedulers.main)
|
.observeOn(aapsSchedulers.main)
|
||||||
|
@ -366,7 +359,7 @@ class LocalProfileFragment : DaggerFragment() {
|
||||||
val isValid = localProfilePlugin.isValidEditState(activity)
|
val isValid = localProfilePlugin.isValidEditState(activity)
|
||||||
val isEdited = localProfilePlugin.isEdited
|
val isEdited = localProfilePlugin.isEdited
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
this.view?.setBackgroundColor(rh.gc(R.color.ok_background))
|
this.view?.setBackgroundColor(rh.gac(context, R.attr.okBackgroundColor))
|
||||||
binding.profileList.isEnabled = true
|
binding.profileList.isEnabled = true
|
||||||
|
|
||||||
if (isEdited) {
|
if (isEdited) {
|
||||||
|
@ -378,7 +371,7 @@ class LocalProfileFragment : DaggerFragment() {
|
||||||
binding.save.visibility = View.GONE
|
binding.save.visibility = View.GONE
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.view?.setBackgroundColor(rh.gc(R.color.error_background))
|
this.view?.setBackgroundColor(rh.gac(context, R.attr.errorBackgroundColor))
|
||||||
binding.profileList.isEnabled = false
|
binding.profileList.isEnabled = false
|
||||||
binding.profileswitch.visibility = View.GONE
|
binding.profileswitch.visibility = View.GONE
|
||||||
binding.save.visibility = View.GONE //don't save an invalid profile
|
binding.save.visibility = View.GONE //don't save an invalid profile
|
||||||
|
@ -392,17 +385,28 @@ class LocalProfileFragment : DaggerFragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processVisibilityOnClick(selected: View) {
|
private fun processVisibility(position: Int) {
|
||||||
binding.diaTab.setBackgroundColor(rh.gc(R.color.defaultbackground))
|
binding.diaPlaceholder.visibility = (position == 0).toVisibility()
|
||||||
binding.icTab.setBackgroundColor(rh.gc(R.color.defaultbackground))
|
binding.ic.visibility = (position == 1).toVisibility()
|
||||||
binding.isfTab.setBackgroundColor(rh.gc(R.color.defaultbackground))
|
binding.isf.visibility = (position == 2).toVisibility()
|
||||||
binding.basalTab.setBackgroundColor(rh.gc(R.color.defaultbackground))
|
binding.basal.visibility = (position == 3).toVisibility()
|
||||||
binding.targetTab.setBackgroundColor(rh.gc(R.color.defaultbackground))
|
binding.target.visibility = (position == 4).toVisibility()
|
||||||
selected.setBackgroundColor(rh.gc(R.color.tabBgColorSelected))
|
}
|
||||||
binding.diaPlaceholder.visibility = View.GONE
|
|
||||||
binding.ic.visibility = View.GONE
|
private fun updateProtectedUi() {
|
||||||
binding.isf.visibility = View.GONE
|
val isLocked = protectionCheck.isLocked(ProtectionCheck.Protection.PREFERENCES)
|
||||||
binding.basal.visibility = View.GONE
|
binding.mainLayout.visibility = isLocked.not().toVisibility()
|
||||||
binding.target.visibility = View.GONE
|
binding.unlock.visibility = isLocked.toVisibility()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun queryProtection() {
|
||||||
|
val isLocked = protectionCheck.isLocked(ProtectionCheck.Protection.PREFERENCES)
|
||||||
|
if (isLocked && !queryingProtection) {
|
||||||
|
activity?.let { activity ->
|
||||||
|
queryingProtection = true
|
||||||
|
val doUpdate = { activity.runOnUiThread { queryingProtection = false; updateProtectedUi() } }
|
||||||
|
protectionCheck.queryProtection(activity, ProtectionCheck.Protection.PREFERENCES, doUpdate, doUpdate, doUpdate)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,10 +52,6 @@ class VirtualPumpFragment : DaggerFragment() {
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
|
@ -137,6 +137,8 @@ class SensitivityAAPSPlugin @Inject constructor(
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun maxAbsorptionHours(): Double = sp.getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME)
|
||||||
|
|
||||||
override val id: SensitivityType
|
override val id: SensitivityType
|
||||||
get() = SensitivityType.SENSITIVITY_AAPS
|
get() = SensitivityType.SENSITIVITY_AAPS
|
||||||
|
|
||||||
|
|
|
@ -53,8 +53,6 @@ class SensitivityOref1Plugin @Inject constructor(
|
||||||
) {
|
) {
|
||||||
|
|
||||||
override fun detectSensitivity(ads: AutosensDataStore, fromTime: Long, toTime: Long): AutosensResult {
|
override fun detectSensitivity(ads: AutosensDataStore, fromTime: Long, toTime: Long): AutosensResult {
|
||||||
// todo this method is called from the IobCobCalculatorPlugin, which leads to a circular
|
|
||||||
// dependency, this should be avoided
|
|
||||||
val profile = profileFunction.getProfile()
|
val profile = profileFunction.getProfile()
|
||||||
if (profile == null) {
|
if (profile == null) {
|
||||||
aapsLogger.error("No profile")
|
aapsLogger.error("No profile")
|
||||||
|
@ -204,6 +202,8 @@ class SensitivityOref1Plugin @Inject constructor(
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun maxAbsorptionHours(): Double = sp.getDouble(R.string.key_absorption_cutoff, Constants.DEFAULT_MAX_ABSORPTION_TIME)
|
||||||
|
|
||||||
override fun configuration(): JSONObject {
|
override fun configuration(): JSONObject {
|
||||||
val c = JSONObject()
|
val c = JSONObject()
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -157,6 +157,8 @@ class SensitivityWeightedAveragePlugin @Inject constructor(
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun maxAbsorptionHours(): Double = sp.getDouble(R.string.key_absorption_maxtime, Constants.DEFAULT_MAX_ABSORPTION_TIME)
|
||||||
|
|
||||||
override val id: SensitivityType
|
override val id: SensitivityType
|
||||||
get() = SensitivityType.SENSITIVITY_WEIGHTED
|
get() = SensitivityType.SENSITIVITY_WEIGHTED
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package info.nightscout.androidaps.plugins.source
|
package info.nightscout.androidaps.plugins.source
|
||||||
|
|
||||||
import android.graphics.Paint
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.util.SparseArray
|
||||||
import android.view.View
|
import android.view.*
|
||||||
import android.view.ViewGroup
|
import androidx.core.util.forEach
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import dagger.android.support.DaggerFragment
|
import dagger.android.support.DaggerFragment
|
||||||
|
@ -26,6 +25,7 @@ import info.nightscout.androidaps.interfaces.PluginBase
|
||||||
import info.nightscout.androidaps.interfaces.ProfileFunction
|
import info.nightscout.androidaps.interfaces.ProfileFunction
|
||||||
import info.nightscout.androidaps.logging.UserEntryLogger
|
import info.nightscout.androidaps.logging.UserEntryLogger
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||||
|
import info.nightscout.androidaps.utils.ActionModeHelper
|
||||||
import info.nightscout.androidaps.utils.DateUtil
|
import info.nightscout.androidaps.utils.DateUtil
|
||||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||||
import info.nightscout.androidaps.utils.T
|
import info.nightscout.androidaps.utils.T
|
||||||
|
@ -54,11 +54,10 @@ class BGSourceFragment : DaggerFragment() {
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
private val millsToThePast = T.hours(36).msecs()
|
private val millsToThePast = T.hours(36).msecs()
|
||||||
|
private lateinit var actionHelper: ActionModeHelper<GlucoseValue>
|
||||||
private var _binding: BgsourceFragmentBinding? = null
|
private var _binding: BgsourceFragmentBinding? = null
|
||||||
|
|
||||||
// This property is only valid between onCreateView and
|
// This property is only valid between onCreateView and onDestroyView.
|
||||||
// onDestroyView.
|
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
|
||||||
|
@ -66,6 +65,10 @@ class BGSourceFragment : DaggerFragment() {
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
actionHelper = ActionModeHelper(rh, activity)
|
||||||
|
actionHelper.setUpdateListHandler { binding.recyclerview.adapter?.notifyDataSetChanged() }
|
||||||
|
actionHelper.setOnRemoveHandler { removeSelected(it) }
|
||||||
|
setHasOptionsMenu(actionHelper.inMenu)
|
||||||
|
|
||||||
binding.recyclerview.setHasFixedSize(true)
|
binding.recyclerview.setHasFixedSize(true)
|
||||||
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
binding.recyclerview.layoutManager = LinearLayoutManager(view.context)
|
||||||
|
@ -94,10 +97,21 @@ class BGSourceFragment : DaggerFragment() {
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
|
actionHelper.finish()
|
||||||
disposable.clear()
|
disposable.clear()
|
||||||
super.onPause()
|
super.onPause()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
|
actionHelper.onCreateOptionsMenu(menu, inflater)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
|
super.onPrepareOptionsMenu(menu)
|
||||||
|
actionHelper.onPrepareOptionsMenu(menu)
|
||||||
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
@ -105,6 +119,9 @@ class BGSourceFragment : DaggerFragment() {
|
||||||
_binding = null
|
_binding = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem) =
|
||||||
|
actionHelper.onOptionsItemSelected(item)
|
||||||
|
|
||||||
inner class RecyclerViewAdapter internal constructor(private var glucoseValues: List<GlucoseValue>) : RecyclerView.Adapter<RecyclerViewAdapter.GlucoseValuesViewHolder>() {
|
inner class RecyclerViewAdapter internal constructor(private var glucoseValues: List<GlucoseValue>) : RecyclerView.Adapter<RecyclerViewAdapter.GlucoseValuesViewHolder>() {
|
||||||
|
|
||||||
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): GlucoseValuesViewHolder {
|
override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): GlucoseValuesViewHolder {
|
||||||
|
@ -116,58 +133,83 @@ class BGSourceFragment : DaggerFragment() {
|
||||||
val glucoseValue = glucoseValues[position]
|
val glucoseValue = glucoseValues[position]
|
||||||
holder.binding.ns.visibility = (glucoseValue.interfaceIDs.nightscoutId != null).toVisibility()
|
holder.binding.ns.visibility = (glucoseValue.interfaceIDs.nightscoutId != null).toVisibility()
|
||||||
holder.binding.invalid.visibility = (!glucoseValue.isValid).toVisibility()
|
holder.binding.invalid.visibility = (!glucoseValue.isValid).toVisibility()
|
||||||
val sameDayPrevious = position > 0 && dateUtil.isSameDay(glucoseValue.timestamp, glucoseValues[position-1].timestamp)
|
val newDay = position == 0 || !dateUtil.isSameDay(glucoseValue.timestamp, glucoseValues[position - 1].timestamp)
|
||||||
holder.binding.date.visibility = sameDayPrevious.not().toVisibility()
|
holder.binding.date.visibility = newDay.toVisibility()
|
||||||
holder.binding.date.text = dateUtil.dateString(glucoseValue.timestamp)
|
holder.binding.date.text = if (newDay) dateUtil.dateStringRelative(glucoseValue.timestamp, rh) else ""
|
||||||
holder.binding.time.text = dateUtil.timeString(glucoseValue.timestamp)
|
holder.binding.time.text = dateUtil.timeString(glucoseValue.timestamp)
|
||||||
holder.binding.value.text = glucoseValue.valueToUnitsString(profileFunction.getUnits())
|
holder.binding.value.text = glucoseValue.valueToUnitsString(profileFunction.getUnits())
|
||||||
holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon())
|
holder.binding.direction.setImageResource(glucoseValue.trendArrow.directionToIcon())
|
||||||
holder.binding.remove.tag = glucoseValue
|
|
||||||
if (position > 0) {
|
if (position > 0) {
|
||||||
val previous = glucoseValues[position - 1]
|
val previous = glucoseValues[position - 1]
|
||||||
val diff = previous.timestamp - glucoseValue.timestamp
|
val diff = previous.timestamp - glucoseValue.timestamp
|
||||||
if (diff < T.secs(20).msecs())
|
if (diff < T.secs(20).msecs())
|
||||||
holder.binding.root.setBackgroundColor(rh.gc(R.color.errorAlertBackground))
|
holder.binding.root.setBackgroundColor(rh.gac(context, R.attr.bgsourceError))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
holder.binding.root.setOnLongClickListener {
|
||||||
|
if (actionHelper.startRemove()) {
|
||||||
|
holder.binding.cbRemove.toggle()
|
||||||
|
actionHelper.updateSelection(position, glucoseValue, holder.binding.cbRemove.isChecked)
|
||||||
|
return@setOnLongClickListener true
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
holder.binding.root.setOnClickListener {
|
||||||
|
if (actionHelper.isRemoving) {
|
||||||
|
holder.binding.cbRemove.toggle()
|
||||||
|
actionHelper.updateSelection(position, glucoseValue, holder.binding.cbRemove.isChecked)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
holder.binding.cbRemove.setOnCheckedChangeListener { _, value ->
|
||||||
|
actionHelper.updateSelection(position, glucoseValue, value)
|
||||||
|
}
|
||||||
|
holder.binding.cbRemove.isChecked = actionHelper.isSelected(position)
|
||||||
|
holder.binding.cbRemove.visibility = actionHelper.isRemoving.toVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int = glucoseValues.size
|
override fun getItemCount() = glucoseValues.size
|
||||||
|
|
||||||
inner class GlucoseValuesViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
inner class GlucoseValuesViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||||
|
|
||||||
val binding = BgsourceItemBinding.bind(view)
|
val binding = BgsourceItemBinding.bind(view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
private fun getConfirmationText(selectedItems: SparseArray<GlucoseValue>): String {
|
||||||
binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG
|
if (selectedItems.size() == 1) {
|
||||||
binding.remove.setOnClickListener { v: View ->
|
val glucoseValue = selectedItems.valueAt(0)
|
||||||
val glucoseValue = v.tag as GlucoseValue
|
return dateUtil.dateAndTimeString(glucoseValue.timestamp) + "\n" + glucoseValue.valueToUnitsString(profileFunction.getUnits())
|
||||||
activity?.let { activity ->
|
}
|
||||||
val text = dateUtil.dateAndTimeString(glucoseValue.timestamp) + "\n" + glucoseValue.valueToUnitsString(profileFunction.getUnits())
|
return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size())
|
||||||
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), text, Runnable {
|
}
|
||||||
val source = when ((activePlugin.activeBgSource as PluginBase).pluginDescription.pluginName) {
|
|
||||||
R.string.dexcom_app_patched -> Sources.Dexcom
|
private fun removeSelected(selectedItems: SparseArray<GlucoseValue>) {
|
||||||
R.string.eversense -> Sources.Eversense
|
activity?.let { activity ->
|
||||||
R.string.Glimp -> Sources.Glimp
|
OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(selectedItems), Runnable {
|
||||||
R.string.MM640g -> Sources.MM640g
|
selectedItems.forEach { _, glucoseValue ->
|
||||||
R.string.nsclientbg -> Sources.NSClientSource
|
val source = when ((activePlugin.activeBgSource as PluginBase).pluginDescription.pluginName) {
|
||||||
R.string.poctech -> Sources.PocTech
|
R.string.dexcom_app_patched -> Sources.Dexcom
|
||||||
R.string.tomato -> Sources.Tomato
|
R.string.eversense -> Sources.Eversense
|
||||||
R.string.glunovo -> Sources.Glunovo
|
R.string.Glimp -> Sources.Glimp
|
||||||
R.string.xdrip -> Sources.Xdrip
|
R.string.MM640g -> Sources.MM640g
|
||||||
else -> Sources.Unknown
|
R.string.nsclientbg -> Sources.NSClientSource
|
||||||
}
|
R.string.poctech -> Sources.PocTech
|
||||||
uel.log(
|
R.string.tomato -> Sources.Tomato
|
||||||
Action.BG_REMOVED, source,
|
R.string.glunovo -> Sources.Glunovo
|
||||||
ValueWithUnit.Timestamp(glucoseValue.timestamp)
|
R.string.xdrip -> Sources.Xdrip
|
||||||
)
|
else -> Sources.Unknown
|
||||||
repository.runTransactionForResult(InvalidateGlucoseValueTransaction(glucoseValue.id))
|
|
||||||
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while invalidating BG value", it) }
|
|
||||||
.blockingGet()
|
|
||||||
.also { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bg $it") } }
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
uel.log(
|
||||||
|
Action.BG_REMOVED, source,
|
||||||
|
ValueWithUnit.Timestamp(glucoseValue.timestamp)
|
||||||
|
)
|
||||||
|
repository.runTransactionForResult(InvalidateGlucoseValueTransaction(glucoseValue.id))
|
||||||
|
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while invalidating BG value", it) }
|
||||||
|
.blockingGet()
|
||||||
|
.also { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bg $it") } }
|
||||||
}
|
}
|
||||||
}
|
actionHelper.finish()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue