Merge pull request #2312 from MilosKozak/dagger3a

Dagger3a
This commit is contained in:
Milos Kozak 2019-12-27 10:28:19 +01:00 committed by GitHub
commit 8f7c4fe145
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
265 changed files with 8502 additions and 7269 deletions

View file

@ -0,0 +1,137 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="AUTODETECT_INDENTS" value="false" />
<AndroidXmlCodeStyleSettings>
<option name="ARRANGEMENT_SETTINGS_MIGRATED_TO_191" value="true" />
</AndroidXmlCodeStyleSettings>
<JetCodeStyleSettings>
<option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="6" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="6" />
<option name="BLANK_LINES_AROUND_BLOCK_WHEN_BRANCHES" value="1" />
</JetCodeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
<option name="LINE_COMMENT_ADD_SPACE" value="true" />
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="1" />
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

View file

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View file

@ -51,12 +51,11 @@
</activity>
<activity android:name=".activities.PreferencesActivity" />
<activity
android:name=".plugins.general.overview.dialogs.BolusProgressHelperActivity"
android:name=".activities.BolusProgressHelperActivity"
android:theme="@style/Theme.AppCompat.Translucent" />
<activity
android:name=".plugins.general.overview.dialogs.ErrorHelperActivity"
android:name=".activities.ErrorHelperActivity"
android:theme="@style/Theme.AppCompat.Translucent" />
<activity android:name=".activities.AgreementActivity" />
<activity android:name=".plugins.pump.danaR.activities.DanaRHistoryActivity" />
<activity android:name=".plugins.pump.danaR.activities.DanaRUserOptionsActivity" />
<activity android:name=".activities.TDDStatsActivity" />
@ -116,7 +115,7 @@
<!-- Auto start -->
<receiver
android:name=".plugins.general.nsclient.receivers.AutoStartReceiver"
android:name=".receivers.AutoStartReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
@ -124,16 +123,6 @@
</intent-filter>
</receiver>
<!-- NSClient -->
<receiver
android:name=".plugins.general.nsclient.receivers.DBAccessReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="info.nightscout.client.DBACCESS" />
</intent-filter>
</receiver>
<!-- Network change local receiver -->
<receiver android:name=".receivers.NetworkChangeReceiver">
<intent-filter>

View file

@ -25,8 +25,6 @@ public class Constants {
public static final int hoursToKeepInDatabase = 72;
public static final int daysToKeepHistoryInDatabase = 30;
public static final long keepAliveMsecs = 5 * 60 * 1000L;
// SMS COMMUNICATOR
public static final long remoteBolusMinDistance = 15 * 60 * 1000L;
@ -82,4 +80,11 @@ public class Constants {
public static final double LOWMARK = 76.0;
public static final double HIGHMARK = 180.0;
// STATISTICS
public static final double STATS_TARGET_LOW_MMOL = 3.9;
public static final double STATS_TARGET_HIGH_MMOL = 7.8;
public static final double STATS_RANGE_LOW_MMOL = 3.9;
public static final double STATS_RANGE_HIGH_MMOL = 10.0;
}

View file

@ -37,13 +37,17 @@ import com.joanzapata.iconify.fonts.FontAwesomeModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import dagger.android.AndroidInjection;
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.activities.HistoryBrowseActivity;
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
import info.nightscout.androidaps.activities.PreferencesActivity;
import info.nightscout.androidaps.activities.SingleFragmentActivity;
import info.nightscout.androidaps.activities.StatsActivity;
import info.nightscout.androidaps.activities.SurveyActivity;
import info.nightscout.androidaps.events.EventAppExit;
import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRebuildTabs;
@ -54,24 +58,33 @@ import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtilsKt;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus;
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
import info.nightscout.androidaps.setupwizard.SetupWizardActivity;
import info.nightscout.androidaps.tabs.TabPageAdapter;
import info.nightscout.androidaps.utils.AndroidPermission;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.LocaleHelper;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.PasswordProtection;
import info.nightscout.androidaps.utils.SP;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
public class MainActivity extends NoSplashAppCompatActivity {
public class MainActivity extends NoSplashAppCompatActivity implements HasAndroidInjector {
private static Logger log = LoggerFactory.getLogger(L.CORE);
@Inject
DispatchingAndroidInjector<Object> androidInjector;
private CompositeDisposable disposable = new CompositeDisposable();
private ActionBarDrawerToggle actionBarDrawerToggle;
private MenuItem pluginPreferencesMenuItem;
@Inject
SmsCommunicatorPlugin smsCommunicatorPlugin;
@Override
public void onCreate(Bundle savedInstanceState) {
AndroidInjection.inject(this);
@ -94,8 +107,6 @@ public class MainActivity extends NoSplashAppCompatActivity {
// initialize screen wake lock
processPreferenceChange(new EventPreferenceChange(R.string.key_keep_screen_on));
doMigrations();
final ViewPager viewPager = findViewById(R.id.pager);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
@ -141,7 +152,7 @@ public class MainActivity extends NoSplashAppCompatActivity {
.subscribe(this::processPreferenceChange, FabricPrivacy::logException)
);
if (!SP.getBoolean(R.string.key_setupwizard_processed, false) || !SP.contains(R.string.key_units)) {
if (!SP.getBoolean(R.string.key_setupwizard_processed, false)) {
Intent intent = new Intent(this, SetupWizardActivity.class);
startActivity(intent);
}
@ -150,7 +161,7 @@ public class MainActivity extends NoSplashAppCompatActivity {
AndroidPermission.notifyForBatteryOptimizationPermission(this);
if (Config.PUMPDRIVERS) {
AndroidPermission.notifyForLocationPermissions(this);
AndroidPermission.notifyForSMSPermissions(this);
AndroidPermission.notifyForSMSPermissions(this, smsCommunicatorPlugin);
}
}
@ -235,17 +246,6 @@ public class MainActivity extends NoSplashAppCompatActivity {
}
}
private void doMigrations() {
// guarantee that the unreachable threshold is at least 30 and of type String
// Added in 1.57 at 21.01.2018
int unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30);
SP.remove(R.string.key_pump_unreachable_threshold);
if (unreachable_threshold < 30) unreachable_threshold = 30;
SP.putString(R.string.key_pump_unreachable_threshold, Integer.toString(unreachable_threshold));
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
@ -254,10 +254,7 @@ public class MainActivity extends NoSplashAppCompatActivity {
switch (requestCode) {
case AndroidPermission.CASE_STORAGE:
//show dialog after permission is granted
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setMessage(R.string.alert_dialog_storage_permission_text);
alert.setPositiveButton(R.string.ok, null);
alert.show();
OKDialog.show(this, "", MainApp.gs(R.string.alert_dialog_storage_permission_text));
break;
case AndroidPermission.CASE_LOCATION:
case AndroidPermission.CASE_SMS:
@ -331,9 +328,7 @@ public class MainActivity extends NoSplashAppCompatActivity {
return true;
case R.id.nav_exit:
log.debug("Exiting");
MainApp.instance().stopKeepAliveService();
RxBus.INSTANCE.send(new EventAppExit());
MainApp.closeDbHelper();
finish();
System.runFinalization();
System.exit(0);
@ -358,4 +353,13 @@ public class MainActivity extends NoSplashAppCompatActivity {
}
return actionBarDrawerToggle.onOptionsItemSelected(item);
}
/**
* Returns an {@link AndroidInjector}.
*/
@Override
public AndroidInjector<Object> androidInjector() {
return androidInjector;
}
}

View file

@ -1,11 +1,13 @@
package info.nightscout.androidaps;
import android.content.BroadcastReceiver;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.SystemClock;
import androidx.annotation.ColorRes;
import androidx.annotation.PluralsRes;
import androidx.annotation.StringRes;
import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.crashlytics.android.Crashlytics;
@ -14,6 +16,7 @@ import com.j256.ormlite.android.apptools.OpenHelperManager;
import net.danlew.android.joda.JodaTimeAndroid;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -25,6 +28,7 @@ import javax.inject.Inject;
import dagger.android.AndroidInjector;
import dagger.android.DaggerApplication;
import info.nightscout.androidaps.data.ConstraintChecker;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.dependencyInjection.DaggerAppComponent;
import info.nightscout.androidaps.interfaces.PluginBase;
@ -36,6 +40,7 @@ import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSMA.OpenAPSMAPlugin;
import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin;
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin;
import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin;
@ -50,8 +55,6 @@ import info.nightscout.androidaps.plugins.general.maintenance.LoggerUtils;
import info.nightscout.androidaps.plugins.general.maintenance.MaintenancePlugin;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.nsclient.receivers.AckAlarmReceiver;
import info.nightscout.androidaps.plugins.general.nsclient.receivers.DBAccessReceiver;
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.general.persistentNotification.PersistentNotificationPlugin;
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorPlugin;
@ -94,7 +97,7 @@ import info.nightscout.androidaps.services.Intents;
import info.nightscout.androidaps.utils.ActivityMonitor;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.LocaleHelper;
import info.nightscout.androidaps.utils.sharedPreferences.SPImpl;
import info.nightscout.androidaps.utils.SP;
import io.fabric.sdk.android.Fabric;
import static info.nightscout.androidaps.plugins.constraints.versionChecker.VersionCheckerUtilsKt.triggerCheckVersion;
@ -102,7 +105,6 @@ import static info.nightscout.androidaps.plugins.constraints.versionChecker.Vers
public class MainApp extends DaggerApplication {
static Logger log = LoggerFactory.getLogger(L.CORE);
static KeepAliveReceiver keepAliveReceiver;
static MainApp sInstance;
public static Resources sResources;
@ -115,18 +117,18 @@ public class MainApp extends DaggerApplication {
static ArrayList<PluginBase> pluginsList = null;
static DataReceiver dataReceiver = new DataReceiver();
static NSAlarmReceiver alarmReciever = new NSAlarmReceiver();
static AckAlarmReceiver ackAlarmReciever = new AckAlarmReceiver();
static DBAccessReceiver dbAccessReciever = new DBAccessReceiver();
LocalBroadcastManager lbm;
BroadcastReceiver btReceiver;
static NSAlarmReceiver alarmReceiver = new NSAlarmReceiver();
TimeDateOrTZChangeReceiver timeDateOrTZChangeReceiver;
public static boolean devBranch;
public static boolean engineeringMode;
@Inject
InsulinOrefFreePeakPlugin insulinOrefFreePeakPlugin;
@Inject ConfigBuilderPlugin configBuilderPlugin;
@Inject InsulinOrefFreePeakPlugin insulinOrefFreePeakPlugin;
@Inject InsulinOrefRapidActingPlugin insulinOrefRapidActingPlugin;
@Inject InsulinOrefUltraRapidActingPlugin insulinOrefUltraRapidActingPlugin;
@Inject SmsCommunicatorPlugin smsCommunicatorPlugin;
@Override
public void onCreate() {
@ -159,7 +161,7 @@ public class MainApp extends DaggerApplication {
registerActivityLifecycleCallbacks(ActivityMonitor.INSTANCE);
mFirebaseAnalytics = FirebaseAnalytics.getInstance(this);
mFirebaseAnalytics.setAnalyticsCollectionEnabled(!Boolean.getBoolean("disableFirebase"));
mFirebaseAnalytics.setAnalyticsCollectionEnabled(!Boolean.getBoolean("disableFirebase") && FabricPrivacy.fabricEnabled());
JodaTimeAndroid.init(this);
@ -177,7 +179,6 @@ public class MainApp extends DaggerApplication {
//trigger here to see the new version on app start after an update
triggerCheckVersion();
//setBTReceiver();
if (pluginsList == null) {
pluginsList = new ArrayList<>();
@ -185,8 +186,8 @@ public class MainApp extends DaggerApplication {
pluginsList.add(OverviewPlugin.INSTANCE);
pluginsList.add(IobCobCalculatorPlugin.getPlugin());
if (!Config.NSCLIENT) pluginsList.add(ActionsPlugin.INSTANCE);
pluginsList.add(InsulinOrefRapidActingPlugin.getPlugin());
pluginsList.add(InsulinOrefUltraRapidActingPlugin.getPlugin());
pluginsList.add(insulinOrefRapidActingPlugin);
pluginsList.add(insulinOrefUltraRapidActingPlugin);
pluginsList.add(insulinOrefFreePeakPlugin);
pluginsList.add(SensitivityOref0Plugin.getPlugin());
pluginsList.add(SensitivityAAPSPlugin.getPlugin());
@ -223,7 +224,7 @@ public class MainApp extends DaggerApplication {
pluginsList.add(SourceTomatoPlugin.getPlugin());
pluginsList.add(SourceEversensePlugin.getPlugin());
pluginsList.add(RandomBgPlugin.INSTANCE);
if (!Config.NSCLIENT) pluginsList.add(SmsCommunicatorPlugin.INSTANCE);
if (!Config.NSCLIENT) pluginsList.add(smsCommunicatorPlugin);
pluginsList.add(FoodPlugin.getPlugin());
pluginsList.add(WearPlugin.initPlugin(this));
@ -234,29 +235,56 @@ public class MainApp extends DaggerApplication {
pluginsList.add(MaintenancePlugin.initPlugin(this));
pluginsList.add(AutomationPlugin.INSTANCE);
pluginsList.add(ConfigBuilderPlugin.getPlugin());
pluginsList.add(configBuilderPlugin);
pluginsList.add(DstHelperPlugin.getPlugin());
ConfigBuilderPlugin.getPlugin().initialize();
configBuilderPlugin.initialize();
}
NSUpload.uploadAppStart();
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
final PumpInterface pump = configBuilderPlugin.getActivePump();
if (pump != null) {
new Thread(() -> {
SystemClock.sleep(5000);
ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Initialization", null);
startKeepAliveService();
configBuilderPlugin.getCommandQueue().readStatus("Initialization", null);
}).start();
}
new Thread(() -> KeepAliveReceiver.setAlarm(this)).start();
doMigrations();
}
private void doMigrations() {
// guarantee that the unreachable threshold is at least 30 and of type String
// Added in 1.57 at 21.01.2018
int unreachable_threshold = SP.getInt(R.string.key_pump_unreachable_threshold, 30);
SP.remove(R.string.key_pump_unreachable_threshold);
if (unreachable_threshold < 30) unreachable_threshold = 30;
SP.putString(R.string.key_pump_unreachable_threshold, Integer.toString(unreachable_threshold));
// 2.5 -> 2.6
if (!SP.contains(R.string.key_units)) {
String newUnits = Constants.MGDL;
Profile p = ProfileFunctions.getInstance().getProfile();
if (p != null && p.getData() != null && p.getData().has("units")) {
try {
newUnits = p.getData().getString("units");
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
}
SP.putString(R.string.key_units, newUnits);
}
}
@Override
protected AndroidInjector<? extends DaggerApplication> applicationInjector() {
return DaggerAppComponent
.builder()
.application(this)
@ -264,7 +292,7 @@ public class MainApp extends DaggerApplication {
}
private void registerLocalBroadcastReceiver() {
lbm = LocalBroadcastManager.getInstance(this);
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_TREATMENT));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_CHANGED_TREATMENT));
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_REMOVED_TREATMENT));
@ -279,39 +307,21 @@ public class MainApp extends DaggerApplication {
lbm.registerReceiver(dataReceiver, new IntentFilter(Intents.ACTION_NEW_CAL));
//register alarms
lbm.registerReceiver(alarmReciever, new IntentFilter(Intents.ACTION_ALARM));
lbm.registerReceiver(alarmReciever, new IntentFilter(Intents.ACTION_ANNOUNCEMENT));
lbm.registerReceiver(alarmReciever, new IntentFilter(Intents.ACTION_CLEAR_ALARM));
lbm.registerReceiver(alarmReciever, new IntentFilter(Intents.ACTION_URGENT_ALARM));
//register ack alarm
lbm.registerReceiver(ackAlarmReciever, new IntentFilter(Intents.ACTION_ACK_ALARM));
//register dbaccess
lbm.registerReceiver(dbAccessReciever, new IntentFilter(Intents.ACTION_DATABASE));
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_ALARM));
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_ANNOUNCEMENT));
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_CLEAR_ALARM));
lbm.registerReceiver(alarmReceiver, new IntentFilter(Intents.ACTION_URGENT_ALARM));
this.timeDateOrTZChangeReceiver = new TimeDateOrTZChangeReceiver();
this.timeDateOrTZChangeReceiver.registerBroadcasts(this);
}
private void startKeepAliveService() {
if (keepAliveReceiver == null) {
keepAliveReceiver = new KeepAliveReceiver();
keepAliveReceiver.setAlarm(this);
}
}
public void stopKeepAliveService() {
if (keepAliveReceiver != null)
KeepAliveReceiver.cancelAlarm(this);
}
public static String gs(int id) {
public static String gs(@StringRes int id) {
return sResources.getString(id);
}
public static String gs(int id, Object... args) {
public static String gs(@StringRes int id, Object... args) {
return sResources.getString(id, args);
}
@ -319,8 +329,8 @@ public class MainApp extends DaggerApplication {
return sResources.getQuantityString(id, quantity, args);
}
public static int gc(int id) {
return sResources.getColor(id);
public static int gc(@ColorRes int id) {
return ContextCompat.getColor(instance(), id);
}
public static MainApp instance() {
@ -331,13 +341,6 @@ public class MainApp extends DaggerApplication {
return sDatabaseHelper;
}
public static void closeDbHelper() {
if (sDatabaseHelper != null) {
sDatabaseHelper.close();
sDatabaseHelper = null;
}
}
public static FirebaseAnalytics getFirebaseAnalytics() {
return mFirebaseAnalytics;
}
@ -440,20 +443,12 @@ public class MainApp extends DaggerApplication {
public void onTerminate() {
if (L.isEnabled(L.CORE))
log.debug("onTerminate");
super.onTerminate();
if (sDatabaseHelper != null) {
sDatabaseHelper.close();
sDatabaseHelper = null;
}
if (btReceiver != null) {
unregisterReceiver(btReceiver);
}
if (timeDateOrTZChangeReceiver != null) {
if (timeDateOrTZChangeReceiver != null)
unregisterReceiver(timeDateOrTZChangeReceiver);
}
unregisterActivityLifecycleCallbacks(ActivityMonitor.INSTANCE);
KeepAliveReceiver.cancelAlarm(this);
super.onTerminate();
}
public static int dpToPx(int dp) {

View file

@ -0,0 +1,14 @@
package info.nightscout.androidaps.activities
import android.os.Bundle
import info.nightscout.androidaps.dialogs.BolusProgressDialog
class BolusProgressHelperActivity : NoSplashAppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
BolusProgressDialog()
.setHelperActivity(this)
.setInsulin(intent.getDoubleExtra("insulin", 0.0))
.show(supportFragmentManager, "BolusProgress")
}
}

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.plugins.general.overview.dialogs
package info.nightscout.androidaps.activities
import android.os.Bundle
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity
import info.nightscout.androidaps.dialogs.ErrorDialog
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.utils.SP

View file

@ -53,6 +53,9 @@ public class MyPreferenceFragment extends PreferenceFragment implements HasAndro
@Inject
InsulinOrefFreePeakPlugin insulinOrefFreePeakPlugin;
@Inject
SmsCommunicatorPlugin smsCommunicatorPlugin;
@Override
public void setArguments(Bundle args) {
super.setArguments(args);
@ -132,7 +135,7 @@ public class MyPreferenceFragment extends PreferenceFragment implements HasAndro
addPreferencesFromResourceIfEnabled(NSClientPlugin.getPlugin(), PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(TidepoolPlugin.INSTANCE, PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(SmsCommunicatorPlugin.INSTANCE, PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(smsCommunicatorPlugin, PluginType.GENERAL);
addPreferencesFromResourceIfEnabled(AutomationPlugin.INSTANCE, PluginType.GENERAL);
addPreferencesFromResource(R.xml.pref_others);

View file

@ -25,7 +25,6 @@ import info.nightscout.androidaps.events.EventPreferenceChange;
import info.nightscout.androidaps.events.EventRebuildTabs;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.insulin.InsulinOrefFreePeakPlugin;
import info.nightscout.androidaps.utils.LocaleHelper;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.SP;
@ -76,7 +75,7 @@ public class PreferencesActivity extends PreferenceActivity implements SharedPre
return;
}
if (key.equals(MainApp.gs(R.string.key_openapsama_useautosens)) && SP.getBoolean(R.string.key_openapsama_useautosens, false)) {
OKDialog.show(this, MainApp.gs(R.string.configbuilder_sensitivity), MainApp.gs(R.string.sensitivity_warning), null);
OKDialog.show(this, MainApp.gs(R.string.configbuilder_sensitivity), MainApp.gs(R.string.sensitivity_warning));
}
updatePrefSummary(myPreferenceFragment.findPreference(key));
}

View file

@ -1,60 +0,0 @@
package info.nightscout.androidaps.activities;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.utils.PasswordProtection;
public class SingleFragmentActivity extends AppCompatActivity {
private PluginBase plugin;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_single_fragment);
this.plugin = MainApp.getPluginsList().get(getIntent().getIntExtra("plugin", -1));
setTitle(plugin.getName());
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.frame_layout,
Fragment.instantiate(this, plugin.pluginDescription.getFragmentClass())).commit();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
else if (item.getItemId() == R.id.nav_plugin_preferences) {
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", () -> {
Intent i = new Intent(this, PreferencesActivity.class);
i.putExtra("id", plugin.getPreferencesId());
startActivity(i);
}, null);
return true;
}
return false;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (plugin.getPreferencesId() != -1)
getMenuInflater().inflate(R.menu.menu_single_fragment, menu);
return super.onCreateOptionsMenu(menu);
}
}

View file

@ -0,0 +1,53 @@
package info.nightscout.androidaps.activities
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.AppCompatActivity
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.utils.LocaleHelper
import info.nightscout.androidaps.utils.PasswordProtection
class SingleFragmentActivity : AppCompatActivity() {
private var plugin: PluginBase? = null
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_single_fragment)
plugin = MainApp.getPluginsList()[intent.getIntExtra("plugin", -1)]
title = plugin?.name
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setDisplayShowHomeEnabled(true)
if (savedInstanceState == null) {
supportFragmentManager.beginTransaction().replace(R.id.frame_layout,
supportFragmentManager.fragmentFactory.instantiate(ClassLoader.getSystemClassLoader(), plugin?.pluginDescription?.fragmentClass!!)).commit()
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
finish()
return true
} else if (item.itemId == R.id.nav_plugin_preferences) {
PasswordProtection.QueryPassword(this, R.string.settings_password, "settings_password", Runnable {
val i = Intent(this, PreferencesActivity::class.java)
i.putExtra("id", plugin?.preferencesId)
startActivity(i)
}, null)
return true
}
return false
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
if (plugin?.preferencesId != -1) menuInflater.inflate(R.menu.menu_single_fragment, menu)
return super.onCreateOptionsMenu(menu)
}
public override fun attachBaseContext(newBase: Context) {
super.attachBaseContext(LocaleHelper.wrap(newBase))
}
}

View file

@ -9,7 +9,6 @@ import info.nightscout.androidaps.utils.TddCalculator
import info.nightscout.androidaps.utils.TirCalculator
import kotlinx.android.synthetic.main.stats_activity.*
class StatsActivity : NoSplashAppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
@ -22,10 +21,10 @@ class StatsActivity : NoSplashAppCompatActivity() {
ok.setOnClickListener { finish() }
stats_reset.setOnClickListener {
OKDialog.showConfirmation(this, MainApp.gs(R.string.doyouwantresetstats)) {
OKDialog.showConfirmation(this, MainApp.gs(R.string.doyouwantresetstats), Runnable {
ActivityMonitor.reset()
recreate()
}
})
}
}
}

View file

@ -4,25 +4,21 @@ import android.os.Bundle
import android.widget.ArrayAdapter
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.FirebaseDatabase
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.defaultProfile.DefaultProfile
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
import info.nightscout.androidaps.plugins.treatments.fragments.ProfileViewerDialog
import info.nightscout.androidaps.dialogs.ProfileViewerDialog
import info.nightscout.androidaps.utils.*
import kotlinx.android.synthetic.main.survey_fragment.*
import kotlinx.android.synthetic.main.survey_activity.*
import org.slf4j.LoggerFactory
import java.util.*
class SurveyActivity : NoSplashAppCompatActivity() {
private val log = LoggerFactory.getLogger(SurveyActivity::class.java)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.survey_fragment)
setContentView(R.layout.survey_activity)
survey_id.text = InstanceId.instanceId()
@ -88,7 +84,7 @@ class SurveyActivity : NoSplashAppCompatActivity() {
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
log.debug("signInAnonymously:success")
val user = auth.currentUser
val user = auth.currentUser // TODO: do we need this, seems unused?
val database = FirebaseDatabase.getInstance().reference
database.child("survey").child(r.id).setValue(r)

View file

@ -589,7 +589,7 @@ public class Profile {
public double getMaxDailyBasal() {
double max = 0d;
for (int hour = 0; hour < 24; hour++) {
double value = getBasalTimeFromMidnight((Integer) (hour * 60 * 60));
double value = getBasalTimeFromMidnight(hour * 60 * 60);
if (value > max) max = value;
}
return max;

View file

@ -1,6 +1,7 @@
package info.nightscout.androidaps.data
import androidx.collection.ArrayMap
import info.nightscout.androidaps.utils.JsonHelper
import org.json.JSONException
import org.json.JSONObject
import org.slf4j.LoggerFactory
@ -40,21 +41,19 @@ class ProfileStore(val data: JSONObject) {
fun getSpecificProfile(profileName: String): Profile? {
var profile: Profile? = null
try {
getStore()?.let { store ->
if (store.has(profileName)) {
profile = cachedObjects[profileName]
if (profile == null) {
val profileObject = store.getJSONObject(profileName)
if (profileObject != null && profileObject.has("units")) {
profile = Profile(profileObject, profileObject.getString("units"))
JsonHelper.safeGetJSONObject(store, profileName, null)?.let { profileObject ->
// take units from profile and if N/A from store
JsonHelper.safeGetStringAllowNull(profileObject, "units", JsonHelper.safeGetString(data, "units"))?.let { units ->
profile = Profile(profileObject, units)
cachedObjects[profileName] = profile
}
}
}
}
} catch (e: JSONException) {
log.error("Unhandled exception", e)
}
return profile
}

View file

@ -194,15 +194,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return newVersion;
}
/**
* Close the database connections and clear any cached DAOs.
*/
@Override
public void close() {
super.close();
}
public long size(String database) {
return DatabaseUtils.queryNumEntries(getReadableDatabase(), database);
}
@ -1602,15 +1593,14 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
queryBuilder.limit(100L);
Where where = queryBuilder.where();
where.ge("date", from);
queryBuilder.setCountOf(true);
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
long count = daoProfileSwitch.countOf(preparedQuery);
// now do query of count + 1
queryBuilder = daoProfileSwitch.queryBuilder();
queryBuilder.orderBy("date", ascending);
queryBuilder.limit(count + 1);
preparedQuery = queryBuilder.prepare();
profileSwitches = daoProfileSwitch.query(preparedQuery);
//add last one without duration
ProfileSwitch last = getLastProfileSwitchWithoutDuration();
if (last != null) {
if (!profileSwitches.contains(last))
profileSwitches.add(last);
}
return profileSwitches;
} catch (SQLException e) {
log.error("Unhandled exception", e);
@ -1618,6 +1608,28 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
return new ArrayList<>();
}
@Nullable
private ProfileSwitch getLastProfileSwitchWithoutDuration() {
try {
Dao<ProfileSwitch, Long> daoProfileSwitch = getDaoProfileSwitch();
List<ProfileSwitch> profileSwitches;
QueryBuilder<ProfileSwitch, Long> queryBuilder = daoProfileSwitch.queryBuilder();
queryBuilder.orderBy("date", false);
queryBuilder.limit(1L);
Where where = queryBuilder.where();
where.eq("durationInMinutes", 0);
PreparedQuery<ProfileSwitch> preparedQuery = queryBuilder.prepare();
profileSwitches = daoProfileSwitch.query(preparedQuery);
if (profileSwitches.size() > 0)
return profileSwitches.get(0);
else
return null;
} catch (SQLException e) {
log.error("Unhandled exception", e);
}
return null;
}
public List<ProfileSwitch> getProfileSwitchEventsFromTime(long mills, boolean ascending) {
try {
Dao<ProfileSwitch, Long> daoProfileSwitch = getDaoProfileSwitch();

View file

@ -11,6 +11,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.utils.DateUtil;
/**
* Created by mike on 27.02.2016.
@ -40,34 +41,47 @@ public class DbRequest {
}
// dbAdd
public DbRequest(String action, String collection, String nsClientID, JSONObject data) {
public DbRequest(String action, String collection, JSONObject data) {
this.action = action;
this.collection = collection;
this.nsClientID = "" + DateUtil.now();
try {
data.put("NSCLIENT_ID", nsClientID);
} catch (JSONException e) {
e.printStackTrace();
}
this.data = data.toString();
this.nsClientID = nsClientID;
this._id = "";
}
// dbUpdate, dbUpdateUnset
public DbRequest(String action, String collection, String nsClientID, String _id, JSONObject data) {
public DbRequest(String action, String collection, String _id, JSONObject data) {
this.action = action;
this.collection = collection;
this.nsClientID = "" + DateUtil.now();
try {
data.put("NSCLIENT_ID", nsClientID);
} catch (JSONException e) {
e.printStackTrace();
}
this.data = data.toString();
this.nsClientID = nsClientID;
this._id = _id;
}
// dbRemove
public DbRequest(String action, String collection, String nsClientID, String _id) {
public DbRequest(String action, String collection,
String _id) {
JSONObject data = new JSONObject();
this.action = action;
this.collection = collection;
this.data = new JSONObject().toString();
this.nsClientID = nsClientID;
this._id = _id;
this.nsClientID = "" + DateUtil.now();
try {
data.put("NSCLIENT_ID", nsClientID);
} catch (JSONException e) {
e.printStackTrace();
}
public String hash() {
return Hashing.sha1().hashString(action + collection + _id + data.toString(), Charsets.UTF_8).toString();
this.data = data.toString();
this._id = _id;
}
public JSONObject toJSON() {

View file

@ -1,11 +1,13 @@
package info.nightscout.androidaps.dependencyInjection
import android.app.Application
import dagger.BindsInstance
import dagger.Component
import dagger.android.AndroidInjectionModule
import dagger.android.AndroidInjector
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.plugins.general.automation.actions.ActionSendSMS
import info.nightscout.androidaps.queue.commands.CommandSetProfile
import info.nightscout.androidaps.services.DataService
import javax.inject.Singleton
@Singleton
@ -19,11 +21,17 @@ import javax.inject.Singleton
)
interface AppComponent : AndroidInjector<MainApp> {
fun injectDataService(service: DataService)
fun injectCommandSetProfile(commandSetProfile: CommandSetProfile)
fun injectActionSendSMS(actionSendSMS: ActionSendSMS)
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: Application): Builder
fun application(mainApp: MainApp): Builder
fun build(): AppComponent
}

View file

@ -1,13 +1,21 @@
package info.nightscout.androidaps.dependencyInjection
import android.app.Application
import android.content.Context
import android.preference.PreferenceManager
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctionImplementation
import info.nightscout.androidaps.plugins.general.automation.actions.ActionSendSMS
import info.nightscout.androidaps.queue.commands.CommandSetProfile
import info.nightscout.androidaps.services.DataService
import info.nightscout.androidaps.utils.resources.ResourceHelper
import info.nightscout.androidaps.utils.resources.ResourceHelperImplementation
import info.nightscout.androidaps.utils.sharedPreferences.SP
import info.nightscout.androidaps.utils.sharedPreferences.SPImpl
import info.nightscout.androidaps.utils.sharedPreferences.SPImplementation
import javax.inject.Singleton
@Module(includes = [AppModule.AppBindings::class])
@ -16,13 +24,34 @@ class AppModule {
@Provides
@Singleton
fun provideSharedPreferences(context: Context): SP {
return SPImpl(PreferenceManager.getDefaultSharedPreferences(context))
return SPImplementation(PreferenceManager.getDefaultSharedPreferences(context))
}
@Provides
@Singleton
fun provideProfileFunction(sp: SP): ProfileFunction {
return ProfileFunctionImplementation(sp)
}
@Provides
@Singleton
fun provideResources(mainApp: MainApp): ResourceHelper {
return ResourceHelperImplementation(mainApp)
}
@Module
interface AppBindings {
@ContributesAndroidInjector
fun bindDataService(): DataService
@ContributesAndroidInjector
fun bindCommandSetProfile(): CommandSetProfile
@ContributesAndroidInjector
fun bindActionSendSMS(): ActionSendSMS
@Binds
fun bindContext(application: Application): Context
fun bindContext(mainApp: MainApp): Context
}
}

View file

@ -3,9 +3,13 @@ package info.nightscout.androidaps.dependencyInjection
import dagger.Module
import dagger.android.ContributesAndroidInjector
import info.nightscout.androidaps.activities.MyPreferenceFragment
import info.nightscout.androidaps.plugins.general.smsCommunicator.SmsCommunicatorFragment
@Module
abstract class FragmentsModule {
@ContributesAndroidInjector
abstract fun contributesPreferencesFragment(): MyPreferenceFragment
@ContributesAndroidInjector
abstract fun contributesSmsCommunicatorFragment(): SmsCommunicatorFragment
}

View file

@ -0,0 +1,159 @@
package info.nightscout.androidaps.dialogs
import android.app.Activity
import android.os.Bundle
import android.os.SystemClock
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import androidx.fragment.app.DialogFragment
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.BolusProgressHelperActivity
import info.nightscout.androidaps.events.EventPumpStatusChanged
import info.nightscout.androidaps.logging.L
import info.nightscout.androidaps.plugins.bus.RxBus.toObservable
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress
import info.nightscout.androidaps.utils.FabricPrivacy
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.dialog_bolusprogress.*
import org.slf4j.LoggerFactory
class BolusProgressDialog : DialogFragment() {
private val log = LoggerFactory.getLogger(L.UI)
private val disposable = CompositeDisposable()
companion object {
private val DEFAULT_STATE = MainApp.gs(R.string.waitingforpump)
@JvmField
var bolusEnded = false
@JvmField
var stopPressed = false
}
private var running = true
private var amount = 0.0
private var state: String? = null
private var helpActivity: BolusProgressHelperActivity? = null
fun setInsulin(amount: Double): BolusProgressDialog {
this.amount = amount
bolusEnded = false
return this
}
fun setHelperActivity(activity: BolusProgressHelperActivity): BolusProgressDialog {
helpActivity = activity
return this
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
isCancelable = true
dialog?.setCanceledOnTouchOutside(false)
return inflater.inflate(R.layout.dialog_bolusprogress, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
overview_bolusprogress_title.text = String.format(MainApp.gs(R.string.overview_bolusprogress_goingtodeliver), amount)
overview_bolusprogress_stop.setOnClickListener {
if (L.isEnabled(L.UI)) log.debug("Stop bolus delivery button pressed")
stopPressed = true
overview_bolusprogress_stoppressed.visibility = View.VISIBLE
overview_bolusprogress_stop.visibility = View.INVISIBLE
ConfigBuilderPlugin.getPlugin().commandQueue.cancelAllBoluses()
}
overview_bolusprogress_progressbar.max = 100
state = savedInstanceState?.getString("state", DEFAULT_STATE) ?: DEFAULT_STATE
overview_bolusprogress_status.text = state
stopPressed = false
}
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
override fun onResume() {
super.onResume()
if (L.isEnabled(L.UI)) log.debug("onResume")
if (!ConfigBuilderPlugin.getPlugin().commandQueue.bolusInQueue())
bolusEnded = true
if (bolusEnded) dismiss()
else running = true
disposable.add(toObservable(EventPumpStatusChanged::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ overview_bolusprogress_status.text = it.getStatus() }) { FabricPrivacy.logException(it) }
)
disposable.add(toObservable(EventDismissBolusProgressIfRunning::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ if (running) dismiss() }) { FabricPrivacy.logException(it) }
)
disposable.add(toObservable(EventOverviewBolusProgress::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
if (L.isEnabled(L.UI)) log.debug("Status: " + it.status + " Percent: " + it.percent)
overview_bolusprogress_status.text = it.status
overview_bolusprogress_progressbar.progress = it.percent
if (it.percent == 100) {
overview_bolusprogress_stop.visibility = View.INVISIBLE
scheduleDismiss()
}
state = it.status
}) { FabricPrivacy.logException(it) }
)
}
override fun dismiss() {
if (L.isEnabled(L.UI)) log.debug("dismiss")
try {
super.dismiss()
} catch (e: IllegalStateException) {
// dialog not running yet. onResume will try again. Set bolusEnded to make extra
// sure onResume will catch this
bolusEnded = true
log.error("Unhandled exception", e)
}
helpActivity?.finish()
}
override fun onPause() {
super.onPause()
if (L.isEnabled(L.UI)) log.debug("onPause")
running = false
disposable.clear()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("state", state)
}
private fun scheduleDismiss() {
if (L.isEnabled(L.UI)) log.debug("scheduleDismiss")
Thread(Runnable {
SystemClock.sleep(5000)
bolusEnded = true
val activity: Activity? = activity
activity?.runOnUiThread {
if (running) {
if (L.isEnabled(L.UI)) log.debug("executing")
try {
dismiss()
} catch (e: Exception) {
log.error("Unhandled exception", e)
}
}
}
}).start()
}
}

View file

@ -0,0 +1,68 @@
package info.nightscout.androidaps.dialogs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.common.base.Joiner
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog
import info.nightscout.androidaps.utils.XdripCalibrations
import kotlinx.android.synthetic.main.dialog_calibration.*
import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat
import java.util.*
class CalibrationDialog : DialogFragmentWithDate() {
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("overview_calibration_bg", overview_calibration_bg.value)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
onCreateViewGeneral()
return inflater.inflate(R.layout.dialog_calibration, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val units = ProfileFunctions.getSystemUnits()
val bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData()?.glucose
?: 0.0, units)
if (units == Constants.MMOL)
overview_calibration_bg.setParams(savedInstanceState?.getDouble("overview_calibration_bg")
?: bg, 2.0, 30.0, 0.1, DecimalFormat("0.0"), false, ok)
else
overview_calibration_bg.setParams(savedInstanceState?.getDouble("overview_calibration_bg")
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, ok)
overview_calibration_units.text = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
}
override fun submit() :Boolean {
val units = ProfileFunctions.getSystemUnits()
val unitLabel = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
val actions: LinkedList<String?> = LinkedList()
val bg = overview_calibration_bg.value
actions.add(MainApp.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(bg) + " " + unitLabel)
if (bg > 0) {
activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.overview_calibration), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
XdripCalibrations.confirmAndSendCalibration(bg, context)
})
}
} else
activity?.let { activity ->
OKDialog.show(activity, MainApp.gs(R.string.overview_calibration), MainApp.gs(R.string.no_action_selected))
}
return true
}
}

View file

@ -0,0 +1,220 @@
package info.nightscout.androidaps.dialogs
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.common.base.Joiner
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.DatabaseHelper
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.treatments.CarbsGenerator
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.*
import kotlinx.android.synthetic.main.dialog_carbs.*
import kotlinx.android.synthetic.main.notes.*
import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat
import java.util.*
import kotlin.math.max
class CarbsDialog : DialogFragmentWithDate() {
companion object {
private const val FAV1_DEFAULT = 5
private const val FAV2_DEFAULT = 10
private const val FAV3_DEFAULT = 20
}
private val maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value().toDouble()
private val textWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) {
validateInputs()
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
}
private fun validateInputs() {
val time = overview_carbs_time.value.toInt()
if (time > 12 * 60 || time < -12 * 60) {
overview_carbs_time.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.constraintapllied))
}
if (overview_carbs_duration.value > 10) {
overview_carbs_duration.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.constraintapllied))
}
if (overview_carbs_carbs.value.toInt() > maxCarbs) {
overview_carbs_carbs.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.carbsconstraintapplied))
}
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("overview_carbs_time", overview_carbs_time.value)
savedInstanceState.putDouble("overview_carbs_duration", overview_carbs_duration.value)
savedInstanceState.putDouble("overview_carbs_carbs", overview_carbs_carbs.value)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
onCreateViewGeneral()
return inflater.inflate(R.layout.dialog_carbs, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
overview_carbs_time.setParams(savedInstanceState?.getDouble("overview_carbs_time")
?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
overview_carbs_duration.setParams(savedInstanceState?.getDouble("overview_carbs_duration")
?: 0.0, 0.0, 10.0, 1.0, DecimalFormat("0"), false, ok, textWatcher)
overview_carbs_carbs.setParams(savedInstanceState?.getDouble("overview_carbs_carbs")
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, ok, textWatcher)
overview_carbs_plus1.text = toSignedString(SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
overview_carbs_plus1.setOnClickListener {
overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value
+ SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT))
validateInputs()
}
overview_carbs_plus2.text = toSignedString(SP.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
overview_carbs_plus2.setOnClickListener {
overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value
+ SP.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT))
validateInputs()
}
overview_carbs_plus3.text = toSignedString(SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
overview_carbs_plus3.setOnClickListener {
overview_carbs_carbs.value = max(0.0, overview_carbs_carbs.value
+ SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT))
validateInputs()
}
DatabaseHelper.actualBg()?.let { bgReading ->
if (bgReading.value < 72)
overview_carbs_hypo_tt.setChecked(true)
}
overview_carbs_hypo_tt.setOnClickListener {
overview_carbs_activity_tt.isChecked = false
overview_carbs_eating_soon_tt.isChecked = false
}
overview_carbs_activity_tt.setOnClickListener {
overview_carbs_hypo_tt.isChecked = false
overview_carbs_eating_soon_tt.isChecked = false
}
overview_carbs_eating_soon_tt.setOnClickListener {
overview_carbs_hypo_tt.isChecked = false
overview_carbs_activity_tt.isChecked = false
}
}
private fun toSignedString(value: Int): String {
return if (value > 0) "+$value" else value.toString()
}
override fun submit(): Boolean {
val carbs = overview_carbs_carbs.value.toInt()
val carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(Constraint(carbs)).value()
val units = ProfileFunctions.getSystemUnits()
val activityTTDuration = DefaultValueHelper.determineActivityTTDuration()
val activityTT = DefaultValueHelper.determineActivityTT()
val eatingSoonTTDuration = DefaultValueHelper.determineEatingSoonTTDuration()
val eatingSoonTT = DefaultValueHelper.determineEatingSoonTT()
val hypoTTDuration = DefaultValueHelper.determineHypoTTDuration()
val hypoTT = DefaultValueHelper.determineHypoTT()
val actions: LinkedList<String?> = LinkedList()
val unitLabel = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
val activitySelected = overview_carbs_activity_tt.isChecked
if (activitySelected)
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(activityTT) + " " + unitLabel + " (" + activityTTDuration + " " + MainApp.gs(R.string.unit_minute_short) + ")</font>")
val eatingSoonSelected = overview_carbs_eating_soon_tt.isChecked
if (eatingSoonSelected)
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + eatingSoonTTDuration + " " + MainApp.gs(R.string.unit_minute_short) + ")</font>")
val hypoSelected = overview_carbs_hypo_tt.isChecked
if (hypoSelected)
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(hypoTT) + " " + unitLabel + " (" + hypoTTDuration + " " + MainApp.gs(R.string.unit_minute_short) + ")</font>")
val timeOffset = overview_carbs_time.value.toInt()
val time = DateUtil.now() + timeOffset * 1000 * 60
if (timeOffset != 0)
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time))
val duration = overview_carbs_duration.value.toInt()
if (duration > 0)
actions.add(MainApp.gs(R.string.duration) + ": " + duration + MainApp.gs(R.string.shorthour))
if (carbsAfterConstraints > 0) {
actions.add(MainApp.gs(R.string.carbs) + ": " + "<font color='" + MainApp.gc(R.color.carbs) + "'>" + MainApp.gs(R.string.format_carbs, carbsAfterConstraints) + "</font>")
if (carbsAfterConstraints != carbs)
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.carbsconstraintapplied) + "</font>")
}
val notes = notes.text.toString()
if (notes.isNotEmpty())
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
if (carbsAfterConstraints > 0 || activitySelected || eatingSoonSelected || hypoSelected) {
activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.carbs), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
if (activitySelected) {
val tempTarget = TempTarget()
.date(System.currentTimeMillis())
.duration(activityTTDuration)
.reason(MainApp.gs(R.string.activity))
.source(Source.USER)
.low(Profile.toMgdl(activityTT, ProfileFunctions.getSystemUnits()))
.high(Profile.toMgdl(activityTT, ProfileFunctions.getSystemUnits()))
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
} else if (eatingSoonSelected) {
val tempTarget = TempTarget()
.date(System.currentTimeMillis())
.duration(eatingSoonTTDuration)
.reason(MainApp.gs(R.string.eatingsoon))
.source(Source.USER)
.low(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits()))
.high(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits()))
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
} else if (hypoSelected) {
val tempTarget = TempTarget()
.date(System.currentTimeMillis())
.duration(hypoTTDuration)
.reason(MainApp.gs(R.string.hypo))
.source(Source.USER)
.low(Profile.toMgdl(hypoTT, ProfileFunctions.getSystemUnits()))
.high(Profile.toMgdl(hypoTT, ProfileFunctions.getSystemUnits()))
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
}
if (carbsAfterConstraints > 0) {
if (duration == 0) {
CarbsGenerator.createCarb(carbsAfterConstraints, time, CareportalEvent.CARBCORRECTION, notes)
} else {
CarbsGenerator.generateCarbs(carbsAfterConstraints, time, duration, notes)
NSUpload.uploadEvent(CareportalEvent.NOTE, DateUtil.now() - 2000, MainApp.gs(R.string.generated_ecarbs_note, carbsAfterConstraints, duration, timeOffset))
}
}
}, null)
}
} else
activity?.let { activity ->
OKDialog.show(activity, MainApp.gs(R.string.carbs), MainApp.gs(R.string.no_action_selected))
}
return true
}
}

View file

@ -0,0 +1,150 @@
package info.nightscout.androidaps.dialogs
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.StringRes
import com.google.common.base.Joiner
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog
import info.nightscout.androidaps.utils.SP
import info.nightscout.androidaps.utils.Translator
import kotlinx.android.synthetic.main.dialog_care.*
import kotlinx.android.synthetic.main.notes.*
import kotlinx.android.synthetic.main.okcancel.*
import org.json.JSONObject
import java.text.DecimalFormat
import java.util.*
class CareDialog : DialogFragmentWithDate() {
enum class EventType {
BGCHECK,
SENSOR_INSERT,
BATTERY_CHANGE
}
private var options: EventType = EventType.BGCHECK
@StringRes
private var event: Int = R.string.none
fun setOptions(options: EventType, @StringRes event: Int): CareDialog {
this.options = options
this.event = event
return this
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("actions_care_bg", actions_care_bg.value)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
onCreateViewGeneral()
return inflater.inflate(R.layout.dialog_care, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
actions_care_icon.setImageResource(when (options) {
EventType.BGCHECK -> R.drawable.icon_cp_bgcheck
EventType.SENSOR_INSERT -> R.drawable.icon_cp_cgm_insert
EventType.BATTERY_CHANGE -> R.drawable.icon_cp_pump_battery
})
actions_care_title.text = MainApp.gs(when (options) {
EventType.BGCHECK -> R.string.careportal_bgcheck
EventType.SENSOR_INSERT -> R.string.careportal_cgmsensorinsert
EventType.BATTERY_CHANGE -> R.string.careportal_pumpbatterychange
})
when (options) {
EventType.SENSOR_INSERT,
EventType.BATTERY_CHANGE -> {
action_care_bg_layout.visibility = View.GONE
actions_care_bgsource.visibility = View.GONE
}
else -> {
}
}
val bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData()?.glucose
?: 0.0, ProfileFunctions.getSystemUnits())
val bgTextWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
if (actions_care_sensor.isChecked) actions_care_meter.isChecked = true
}
}
if (ProfileFunctions.getSystemUnits() == Constants.MMOL) {
actions_care_bgunits.text = MainApp.gs(R.string.mmol)
actions_care_bg.setParams(savedInstanceState?.getDouble("actions_care_bg")
?: bg, 2.0, 30.0, 0.1, DecimalFormat("0.0"), false, ok, bgTextWatcher)
} else {
actions_care_bgunits.text = MainApp.gs(R.string.mgdl)
actions_care_bg.setParams(savedInstanceState?.getDouble("actions_care_bg")
?: bg, 36.0, 500.0, 1.0, DecimalFormat("0"), false, ok, bgTextWatcher)
}
}
override fun submit(): Boolean {
val enteredBy = SP.getString("careportal_enteredby", "")
val unitResId = if (ProfileFunctions.getSystemUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol
val json = JSONObject()
val actions: LinkedList<String> = LinkedList()
if (options == EventType.BGCHECK) {
val type =
when {
actions_care_meter.isChecked -> "Finger"
actions_care_sensor.isChecked -> "Sensor"
else -> "Manual"
}
actions.add(MainApp.gs(R.string.careportal_newnstreatment_glucosetype) + ": " + Translator.translate(type))
actions.add(MainApp.gs(R.string.treatments_wizard_bg_label) + ": " + Profile.toCurrentUnitsString(actions_care_bg.value) + " " + MainApp.gs(unitResId))
json.put("glucose", actions_care_bg.value)
json.put("glucoseType", type)
}
val notes = notes.text.toString()
if (notes.isNotEmpty()) {
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
json.put("notes", notes)
}
if (eventTimeChanged)
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
json.put("created_at", DateUtil.toISOString(eventTime))
json.put("eventType", when (options) {
EventType.BGCHECK -> CareportalEvent.BGCHECK
EventType.SENSOR_INSERT -> CareportalEvent.SENSORCHANGE
EventType.BATTERY_CHANGE -> CareportalEvent.PUMPBATTERYCHANGE
})
json.put("units", ProfileFunctions.getSystemUnits())
if (enteredBy.isNotEmpty())
json.put("enteredBy", enteredBy)
activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(event), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
MainApp.getDbHelper().createCareportalEventFromJsonIfNotExists(json)
NSUpload.uploadCareportalEntryToNS(json)
}, null)
}
return true
}
}

View file

@ -0,0 +1,124 @@
package info.nightscout.androidaps.dialogs
import android.app.DatePickerDialog
import android.app.TimePickerDialog
import android.os.Bundle
import android.text.format.DateFormat
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import androidx.fragment.app.DialogFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.SP
import info.nightscout.androidaps.utils.toVisibility
import kotlinx.android.synthetic.main.datetime.*
import kotlinx.android.synthetic.main.notes.*
import kotlinx.android.synthetic.main.okcancel.*
import org.slf4j.LoggerFactory
import java.util.*
abstract class DialogFragmentWithDate : DialogFragment() {
private val log = LoggerFactory.getLogger(DialogFragmentWithDate::class.java)
var eventTime = DateUtil.now()
var eventTimeChanged = false
//one shot guards
private var okClicked: Boolean = false
companion object {
private var seconds: Int = (Math.random() * 59.0).toInt()
}
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putLong("eventTime", eventTime)
savedInstanceState.putBoolean("eventTimeChanged", eventTimeChanged)
}
fun onCreateViewGeneral() {
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
isCancelable = true
dialog?.setCanceledOnTouchOutside(false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
eventTime = savedInstanceState?.getLong("eventTime") ?: DateUtil.now()
eventTimeChanged = savedInstanceState?.getBoolean("eventTimeChanged") ?: false
overview_eventdate?.text = DateUtil.dateString(eventTime)
overview_eventtime?.text = DateUtil.timeString(eventTime)
// create an OnDateSetListener
val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth ->
val cal = Calendar.getInstance()
cal.timeInMillis = eventTime
cal.set(Calendar.YEAR, year)
cal.set(Calendar.MONTH, monthOfYear)
cal.set(Calendar.DAY_OF_MONTH, dayOfMonth)
eventTime = cal.timeInMillis
eventTimeChanged = true
overview_eventdate?.text = DateUtil.dateString(eventTime)
}
overview_eventdate?.setOnClickListener {
context?.let {
val cal = Calendar.getInstance()
cal.timeInMillis = eventTime
DatePickerDialog(it, dateSetListener,
cal.get(Calendar.YEAR),
cal.get(Calendar.MONTH),
cal.get(Calendar.DAY_OF_MONTH)
).show()
}
}
// create an OnTimeSetListener
val timeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
val cal = Calendar.getInstance()
cal.timeInMillis = eventTime
cal.set(Calendar.HOUR_OF_DAY, hour)
cal.set(Calendar.MINUTE, minute)
cal.set(Calendar.SECOND, seconds++) // randomize seconds to prevent creating record of the same time, if user choose time manually
eventTime = cal.timeInMillis
eventTimeChanged = true
overview_eventtime?.text = DateUtil.timeString(eventTime)
}
overview_eventtime?.setOnClickListener {
context?.let {
val cal = Calendar.getInstance()
cal.timeInMillis = eventTime
TimePickerDialog(it, timeSetListener,
cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE),
DateFormat.is24HourFormat(context)
).show()
}
}
notes_layout?.visibility = SP.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
ok.setOnClickListener {
synchronized(okClicked) {
if (okClicked) {
log.debug("guarding: ok already clicked")
} else {
okClicked = true
if (submit()) dismiss()
else okClicked = false
}
}
}
cancel.setOnClickListener { dismiss() }
}
abstract fun submit(): Boolean
}

View file

@ -1,5 +1,4 @@
package info.nightscout.androidaps.plugins.general.overview.dialogs
package info.nightscout.androidaps.dialogs
import android.content.Intent
import android.os.Build
@ -7,11 +6,14 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import androidx.fragment.app.DialogFragment
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.services.AlarmSoundService
import kotlinx.android.synthetic.main.overview_error_dialog.*
import kotlinx.android.synthetic.main.dialog_error.*
import org.slf4j.LoggerFactory
class ErrorDialog : DialogFragment() {
@ -24,20 +26,23 @@ class ErrorDialog : DialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
dialog?.setTitle(title)
isCancelable = false
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
isCancelable = true
dialog?.setCanceledOnTouchOutside(false)
savedInstanceState?.let { bundle ->
bundle.getString("status")?.let { status = it }
bundle.getString("title")?.let { title = it }
sound = bundle.getInt("sound", R.raw.error)
}
return inflater.inflate(R.layout.overview_error_dialog, container, false)
return inflater.inflate(R.layout.dialog_error, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
error_title.text = title
overview_error_ok.setOnClickListener {
log.debug("Error dialog ok button pressed")
dismiss()
@ -56,9 +61,13 @@ class ErrorDialog : DialogFragment() {
bundle.putInt("sound", sound)
}
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
override fun onResume() {
super.onResume()
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
overview_error_status.text = status
}

View file

@ -0,0 +1,82 @@
package info.nightscout.androidaps.dialogs
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.common.base.Joiner
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog
import info.nightscout.androidaps.utils.SafeParse
import kotlinx.android.synthetic.main.dialog_extendedbolus.*
import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat
import java.util.*
import kotlin.math.abs
class ExtendedBolusDialog : DialogFragmentWithDate() {
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("actions_extendedbolus_insulin", actions_extendedbolus_insulin.value)
savedInstanceState.putDouble("actions_extendedbolus_duration", actions_extendedbolus_duration.value)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
onCreateViewGeneral()
return inflater.inflate(R.layout.dialog_extendedbolus, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription ?: return
val maxInsulin = MainApp.getConstraintChecker().maxExtendedBolusAllowed.value()
val extendedStep = pumpDescription.extendedBolusStep
actions_extendedbolus_insulin.setParams(savedInstanceState?.getDouble("actions_extendedbolus_insulin")
?: extendedStep, extendedStep, maxInsulin, extendedStep, DecimalFormat("0.00"), false, ok)
val extendedDurationStep = pumpDescription.extendedBolusDurationStep
val extendedMaxDuration = pumpDescription.extendedBolusMaxDuration
actions_extendedbolus_duration.setParams(savedInstanceState?.getDouble("actions_extendedbolus_duration")
?: extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, DecimalFormat("0"), false, ok)
}
override fun submit(): Boolean {
val insulin = SafeParse.stringToDouble(actions_extendedbolus_insulin.text)
val durationInMinutes = SafeParse.stringToInt(actions_extendedbolus_duration.text)
val actions: LinkedList<String> = LinkedList()
val insulinAfterConstraint = MainApp.getConstraintChecker().applyExtendedBolusConstraints(Constraint(insulin)).value()
actions.add(MainApp.gs(R.string.formatinsulinunits, insulinAfterConstraint))
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, durationInMinutes))
if (abs(insulinAfterConstraint - insulin) > 0.01)
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.constraintapllied) + "</font>")
activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.extended_bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
ConfigBuilderPlugin.getPlugin().commandQueue.extendedBolus(insulinAfterConstraint, durationInMinutes, object : Callback() {
override fun run() {
if (!result.success) {
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment)
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
MainApp.instance().startActivity(i)
}
}
})
}, null)
}
return true
}
}

View file

@ -0,0 +1,132 @@
package info.nightscout.androidaps.dialogs
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.common.base.Joiner
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.*
import kotlinx.android.synthetic.main.dialog_fill.*
import kotlinx.android.synthetic.main.notes.*
import kotlinx.android.synthetic.main.okcancel.*
import java.util.*
import kotlin.math.abs
class FillDialog : DialogFragmentWithDate() {
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("fill_insulinamount", fill_insulinamount.value)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
onCreateViewGeneral()
return inflater.inflate(R.layout.dialog_fill, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val maxInsulin = MainApp.getConstraintChecker().maxBolusAllowed.value()
val bolusStep = ConfigBuilderPlugin.getPlugin().activePump!!.pumpDescription.bolusStep
fill_insulinamount.setParams(savedInstanceState?.getDouble("fill_insulinamount")
?: 0.0, 0.0, maxInsulin, bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), true, ok)
val amount1 = SP.getDouble("fill_button1", 0.3)
if (amount1 > 0) {
fill_preset_button1.visibility = View.VISIBLE
fill_preset_button1.text = DecimalFormatter.toPumpSupportedBolus(amount1) // + "U");
fill_preset_button1.setOnClickListener { fill_insulinamount.value = amount1 }
} else {
fill_preset_button1.visibility = View.GONE
}
val amount2 = SP.getDouble("fill_button2", 0.0)
if (amount2 > 0) {
fill_preset_button2.visibility = View.VISIBLE
fill_preset_button2.text = DecimalFormatter.toPumpSupportedBolus(amount2) // + "U");
fill_preset_button2.setOnClickListener { fill_insulinamount.value = amount2 }
} else {
fill_preset_button2.visibility = View.GONE
}
val amount3 = SP.getDouble("fill_button3", 0.0)
if (amount3 > 0) {
fill_preset_button3.visibility = View.VISIBLE
fill_preset_button3.text = DecimalFormatter.toPumpSupportedBolus(amount3) // + "U");
fill_preset_button3.setOnClickListener { fill_insulinamount.value = amount3 }
} else {
fill_preset_button3.visibility = View.GONE
}
}
override fun submit(): Boolean {
val insulin = SafeParse.stringToDouble(fill_insulinamount.text)
val actions: LinkedList<String?> = LinkedList()
val insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(insulin)).value()
if (insulinAfterConstraints > 0) {
actions.add(MainApp.gs(R.string.fillwarning))
actions.add("")
actions.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.colorInsulinButton) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + MainApp.gs(R.string.insulin_unit_shortname) + "</font>")
if (abs(insulinAfterConstraints - insulin) > 0.01)
actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints))
}
val siteChange = fill_catheter_change.isChecked
if (siteChange)
actions.add("" + "<font color='" + MainApp.gc(R.color.actionsConfirm) + "'>" + MainApp.gs(R.string.record_pump_site_change) + "</font>")
val insulinChange = fill_cartridge_change.isChecked
if (insulinChange)
actions.add("" + "<font color='" + MainApp.gc(R.color.actionsConfirm) + "'>" + MainApp.gs(R.string.record_insulin_cartridge_change) + "</font>")
val notes = notes.text.toString()
if (notes.isNotEmpty())
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
if (eventTimeChanged)
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
if (insulinAfterConstraints > 0 || fill_catheter_change.isChecked || fill_cartridge_change.isChecked) {
activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.primefill), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
if (insulinAfterConstraints > 0) {
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.insulin = insulinAfterConstraints
detailedBolusInfo.context = context
detailedBolusInfo.source = Source.USER
detailedBolusInfo.isValid = false // do not count it in IOB (for pump history)
detailedBolusInfo.notes = notes
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {
if (!result.success) {
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment)
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
MainApp.instance().startActivity(i)
}
}
})
}
if (siteChange) NSUpload.uploadEvent(CareportalEvent.SITECHANGE, eventTime, notes)
if (insulinChange) NSUpload.uploadEvent(CareportalEvent.INSULINCHANGE, eventTime + 1000, notes)
}, null)
}
} else {
activity?.let { activity ->
OKDialog.show(activity, MainApp.gs(R.string.primefill), MainApp.gs(R.string.no_action_selected))
}
}
dismiss()
return true
}
}

View file

@ -0,0 +1,193 @@
package info.nightscout.androidaps.dialogs
import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.common.base.Joiner
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.*
import kotlinx.android.synthetic.main.dialog_insulin.*
import kotlinx.android.synthetic.main.notes.*
import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat
import java.util.*
import kotlin.math.abs
import kotlin.math.max
class InsulinDialog : DialogFragmentWithDate() {
companion object {
private const val PLUS1_DEFAULT = 0.5
private const val PLUS2_DEFAULT = 1.0
private const val PLUS3_DEFAULT = 2.0
}
private val maxInsulin = MainApp.getConstraintChecker().maxBolusAllowed.value()
private val textWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) {
validateInputs()
}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
}
private fun validateInputs() {
if (abs(overview_insulin_time.value.toInt()) > 12 * 60) {
overview_insulin_time.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.constraintapllied))
}
if (overview_insulin_amount.value > maxInsulin) {
overview_insulin_amount.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.bolusconstraintapplied))
}
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("overview_insulin_time", overview_insulin_time.value)
savedInstanceState.putDouble("overview_insulin_amount", overview_insulin_amount.value)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
onCreateViewGeneral()
return inflater.inflate(R.layout.dialog_insulin, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
overview_insulin_time.setParams(savedInstanceState?.getDouble("overview_insulin_time")
?: 0.0, -12 * 60.0, 12 * 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher)
overview_insulin_amount.setParams(savedInstanceState?.getDouble("overview_insulin_amount")
?: 0.0, 0.0, maxInsulin, ConfigBuilderPlugin.getPlugin().activePump!!.pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, ok, textWatcher)
overview_insulin_plus05.text = toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
overview_insulin_plus05.setOnClickListener {
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT))
validateInputs()
}
overview_insulin_plus10.text = toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
overview_insulin_plus10.setOnClickListener {
overview_insulin_amount.value = max(0.0, overview_insulin_amount.value
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT))
validateInputs()
}
overview_insulin_plus20.text = toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
overview_insulin_plus20.setOnClickListener {
overview_insulin_amount.value = Math.max(0.0, overview_insulin_amount.value
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT))
validateInputs()
}
overview_insulin_time_layout.visibility = View.GONE
overview_insulin_record_only.setOnCheckedChangeListener { _, isChecked: Boolean ->
overview_insulin_time_layout.visibility = isChecked.toVisibility()
}
}
private fun toSignedString(value: Double): String {
val formatted = DecimalFormatter.toPumpSupportedBolus(value)
return if (value > 0) "+$formatted" else formatted
}
override fun submit(): Boolean {
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription
?: return false
val insulin = SafeParse.stringToDouble(overview_insulin_amount.text)
val insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(insulin)).value()
val actions: LinkedList<String?> = LinkedList()
val units = ProfileFunctions.getSystemUnits()
val unitLabel = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
val recordOnlyChecked = overview_insulin_record_only.isChecked
val eatingSoonChecked = overview_insulin_start_eating_soon_tt.isChecked
if (insulinAfterConstraints > 0) {
actions.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.bolus) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + MainApp.gs(R.string.insulin_unit_shortname) + "</font>")
if (recordOnlyChecked)
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.bolusrecordedonly) + "</font>")
if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints))
}
val eatingSoonTTDuration = DefaultValueHelper.determineEatingSoonTTDuration()
val eatingSoonTT = DefaultValueHelper.determineEatingSoonTT()
if (eatingSoonChecked)
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(eatingSoonTT) + " " + unitLabel + " (" + eatingSoonTTDuration + " " + MainApp.gs(R.string.unit_minute_short) + ")</font>")
val timeOffset = overview_insulin_time.value.toInt()
val time = DateUtil.now() + T.mins(timeOffset.toLong()).msecs()
if (timeOffset != 0)
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time))
val notes = notes.text.toString()
if (notes.isNotEmpty())
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
if (insulinAfterConstraints > 0 || eatingSoonChecked) {
activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.bolus), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
if (eatingSoonChecked) {
val tempTarget = TempTarget()
.date(System.currentTimeMillis())
.duration(eatingSoonTTDuration)
.reason(MainApp.gs(R.string.eatingsoon))
.source(Source.USER)
.low(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits()))
.high(Profile.toMgdl(eatingSoonTT, ProfileFunctions.getSystemUnits()))
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
}
if (insulinAfterConstraints > 0) {
val detailedBolusInfo = DetailedBolusInfo()
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS
detailedBolusInfo.insulin = insulinAfterConstraints
detailedBolusInfo.context = context
detailedBolusInfo.source = Source.USER
detailedBolusInfo.notes = notes
if (recordOnlyChecked) {
detailedBolusInfo.date = time
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false)
} else {
detailedBolusInfo.date = DateUtil.now()
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {
if (!result.success) {
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment)
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
MainApp.instance().startActivity(i)
}
}
})
}
}
})
}
} else
activity?.let { activity ->
OKDialog.show(activity, MainApp.gs(R.string.bolus), MainApp.gs(R.string.no_action_selected))
}
return true
}
}

View file

@ -0,0 +1,105 @@
package info.nightscout.androidaps.dialogs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import com.google.common.base.Joiner
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog
import kotlinx.android.synthetic.main.dialog_profileswitch.*
import kotlinx.android.synthetic.main.notes.*
import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat
import java.util.*
class ProfileSwitchDialog : DialogFragmentWithDate() {
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("overview_profileswitch_duration", overview_profileswitch_duration.value)
savedInstanceState.putDouble("overview_profileswitch_percentage", overview_profileswitch_percentage.value)
savedInstanceState.putDouble("overview_profileswitch_timeshift", overview_profileswitch_timeshift.value)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
onCreateViewGeneral()
return inflater.inflate(R.layout.dialog_profileswitch, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
overview_profileswitch_duration.setParams(savedInstanceState?.getDouble("overview_profileswitch_duration")
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, ok)
overview_profileswitch_percentage.setParams(savedInstanceState?.getDouble("overview_profileswitch_percentage")
?: 100.0, Constants.CPP_MIN_PERCENTAGE.toDouble(), Constants.CPP_MAX_PERCENTAGE.toDouble(), 1.0, DecimalFormat("0"), false, ok)
overview_profileswitch_timeshift.setParams(savedInstanceState?.getDouble("overview_profileswitch_timeshift")
?: 0.0, Constants.CPP_MIN_TIMESHIFT.toDouble(), Constants.CPP_MAX_TIMESHIFT.toDouble(), 1.0, DecimalFormat("0"), false, ok)
// profile
context?.let { context ->
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile
?: return
val profileList = profileStore.getProfileList()
val adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList)
overview_profileswitch_profile.adapter = adapter
// set selected to actual profile
for (p in profileList.indices)
if (profileList[p] == ProfileFunctions.getInstance().getProfileName(false))
overview_profileswitch_profile.setSelection(p)
} ?: return
TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now())?.let { ps ->
if (ps.isCPP) {
overview_profileswitch_reuselayout.visibility = View.VISIBLE
overview_profileswitch_reusebutton.text = MainApp.gs(R.string.reuse) + " " + ps.percentage + "% " + ps.timeshift + "h"
overview_profileswitch_reusebutton.setOnClickListener {
overview_profileswitch_percentage.value = ps.percentage.toDouble()
overview_profileswitch_timeshift.value = ps.timeshift.toDouble()
}
} else {
overview_profileswitch_reuselayout.visibility = View.GONE
}
}
}
override fun submit(): Boolean {
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile
?: return false
val actions: LinkedList<String> = LinkedList()
val duration = overview_profileswitch_duration.value
if (duration > 0)
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_hours, duration))
val profile = overview_profileswitch_profile.selectedItem.toString()
actions.add(MainApp.gs(R.string.profile) + ": " + profile)
val percent = overview_profileswitch_percentage.value.toInt()
if (percent != 100)
actions.add(MainApp.gs(R.string.percent) + ": " + percent + "%")
val timeShift = overview_profileswitch_timeshift.value.toInt()
if (timeShift != 0)
actions.add(MainApp.gs(R.string.careportal_newnstreatment_timeshift_label) + ": " + MainApp.gs(R.string.format_hours, timeShift.toDouble()))
val notes = notes.text.toString()
if (notes.isNotEmpty())
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes)
if (eventTimeChanged)
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.careportal_profileswitch), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
ProfileFunctions.getInstance().doProfileSwitch(profileStore, profile, duration.toInt(), percent, timeShift, eventTime)
})
}
return true
}
}

View file

@ -1,20 +1,20 @@
package info.nightscout.androidaps.plugins.treatments.fragments
package info.nightscout.androidaps.dialogs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import androidx.fragment.app.DialogFragment
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.interfaces.ProfileInterface
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil
import kotlinx.android.synthetic.main.close.*
import kotlinx.android.synthetic.main.profileviewer_fragment.*
import kotlinx.android.synthetic.main.dialog_profileviewer.*
import org.json.JSONObject
class ProfileViewerDialog : DialogFragment() {
@ -22,8 +22,7 @@ class ProfileViewerDialog : DialogFragment() {
enum class Mode(val i: Int) {
RUNNING_PROFILE(1),
PUMP_PROFILE(2),
CUSTOM_PROFILE(3)
CUSTOM_PROFILE(2)
}
private var mode: Mode = Mode.RUNNING_PROFILE
@ -42,17 +41,18 @@ class ProfileViewerDialog : DialogFragment() {
customProfileName = bundle.getString("customProfileName", "")
}
return inflater.inflate(R.layout.profileviewer_fragment, container, false)
dialog?.window?.requestFeature(Window.FEATURE_NO_TITLE)
dialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
isCancelable = true
dialog?.setCanceledOnTouchOutside(false)
return inflater.inflate(R.layout.dialog_profileviewer, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
close.setOnClickListener { dismiss() }
profileview_reload.setOnClickListener {
ConfigBuilderPlugin.getPlugin().commandQueue.readStatus("ProfileViewDialog", null)
dismiss()
}
val profile: Profile?
val profileName: String?
@ -63,21 +63,13 @@ class ProfileViewerDialog : DialogFragment() {
profileName = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.customizedName
date = DateUtil.dateAndTimeString(TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(time)?.date
?: 0)
profileview_reload.visibility = View.GONE
profileview_datelayout.visibility = View.VISIBLE
}
Mode.PUMP_PROFILE -> {
profile = (ConfigBuilderPlugin.getPlugin().activePump as ProfileInterface?)?.profile?.getDefaultProfile()
profileName = (ConfigBuilderPlugin.getPlugin().activePump as ProfileInterface?)?.profileName
date = ""
profileview_reload.visibility = View.VISIBLE
profileview_datelayout.visibility = View.GONE
}
Mode.CUSTOM_PROFILE -> {
profile = Profile(JSONObject(customProfileJson), customProfileUnits)
profileName = customProfileName
date = ""
profileview_reload.visibility = View.GONE
profileview_datelayout.visibility = View.GONE
}
}
@ -99,9 +91,9 @@ class ProfileViewerDialog : DialogFragment() {
}
}
override fun onResume() {
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
super.onResume()
}
override fun onSaveInstanceState(bundle: Bundle) {

View file

@ -0,0 +1,115 @@
package info.nightscout.androidaps.dialogs
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.common.base.Joiner
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.interfaces.PumpDescription
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog
import info.nightscout.androidaps.utils.SafeParse
import kotlinx.android.synthetic.main.dialog_tempbasal.*
import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat
import java.util.*
import kotlin.math.abs
class TempBasalDialog : DialogFragmentWithDate() {
private var isPercentPump = true
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("actions_tempbasal_duration", actions_tempbasal_duration.value)
savedInstanceState.putDouble("actions_tempbasal_basalpercentinput", actions_tempbasal_basalpercentinput.value)
savedInstanceState.putDouble("actions_tempbasal_basalabsoluteinput", actions_tempbasal_basalabsoluteinput.value)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
onCreateViewGeneral()
return inflater.inflate(R.layout.dialog_tempbasal, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription ?: return
val profile = ProfileFunctions.getInstance().getProfile() ?: return
val maxTempPercent = pumpDescription.maxTempPercent.toDouble()
val tempPercentStep = pumpDescription.tempPercentStep.toDouble()
actions_tempbasal_basalpercentinput.setParams(savedInstanceState?.getDouble("actions_tempbasal_basalpercentinput")
?: 100.0, 0.0, maxTempPercent, tempPercentStep, DecimalFormat("0"), true, ok)
actions_tempbasal_basalabsoluteinput.setParams(savedInstanceState?.getDouble("actions_tempbasal_basalabsoluteinput")
?: profile.basal, 0.0, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, DecimalFormat("0.00"), true, ok)
val tempDurationStep = pumpDescription.tempDurationStep.toDouble()
val tempMaxDuration = pumpDescription.tempMaxDuration.toDouble()
actions_tempbasal_duration.setParams(savedInstanceState?.getDouble("actions_tempbasal_duration")
?: tempDurationStep, tempDurationStep, tempMaxDuration, tempDurationStep, DecimalFormat("0"), false, ok)
isPercentPump = pumpDescription.tempBasalStyle and PumpDescription.PERCENT == PumpDescription.PERCENT
if (isPercentPump) {
actions_tempbasal_percent_layout.visibility = View.VISIBLE
actions_tempbasal_absolute_layout.visibility = View.GONE
} else {
actions_tempbasal_percent_layout.visibility = View.GONE
actions_tempbasal_absolute_layout.visibility = View.VISIBLE
}
}
override fun submit(): Boolean {
var percent = 0
var absolute = 0.0
val durationInMinutes = SafeParse.stringToInt(actions_tempbasal_duration.text)
val profile = ProfileFunctions.getInstance().getProfile() ?: return false
val actions: LinkedList<String> = LinkedList()
if (isPercentPump) {
val basalPercentInput = SafeParse.stringToInt(actions_tempbasal_basalpercentinput.text)
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(Constraint(basalPercentInput), profile).value()
actions.add(MainApp.gs(R.string.pump_tempbasal_label)+ ": $percent%")
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, durationInMinutes))
if (percent != basalPercentInput) actions.add(MainApp.gs(R.string.constraintapllied))
} else {
val basalAbsoluteInput = SafeParse.stringToDouble(actions_tempbasal_basalabsoluteinput.text)
absolute = MainApp.getConstraintChecker().applyBasalConstraints(Constraint(basalAbsoluteInput), profile).value()
actions.add(MainApp.gs(R.string.pump_tempbasal_label)+ ": " + MainApp.gs(R.string.pump_basebasalrate, absolute))
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_mins, durationInMinutes))
if (abs(absolute - basalAbsoluteInput) > 0.01)
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.constraintapllied) + "</font>")
}
activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.pump_tempbasal_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
val callback: Callback = object : Callback() {
override fun run() {
if (!result.success) {
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment)
i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
MainApp.instance().startActivity(i)
}
}
}
if (isPercentPump) {
ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalPercent(percent, durationInMinutes, true, profile, callback)
} else {
ConfigBuilderPlugin.getPlugin().commandQueue.tempBasalAbsolute(absolute, durationInMinutes, true, profile, callback)
}
})
}
return true
}
}

View file

@ -0,0 +1,152 @@
package info.nightscout.androidaps.dialogs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import com.google.common.base.Joiner
import com.google.common.collect.Lists
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.db.TempTarget
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.DefaultValueHelper
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog
import info.nightscout.androidaps.utils.SP
import kotlinx.android.synthetic.main.dialog_temptarget.*
import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat
import java.util.*
class TempTargetDialog : DialogFragmentWithDate() {
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("overview_temptarget_duration", overview_temptarget_duration.value)
savedInstanceState.putDouble("overview_temptarget_temptarget", overview_temptarget_temptarget.value)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
onCreateViewGeneral()
return inflater.inflate(R.layout.dialog_temptarget, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
overview_temptarget_duration.setParams(savedInstanceState?.getDouble("overview_temptarget_duration")
?: 0.0, 0.0, Constants.MAX_PROFILE_SWITCH_DURATION, 10.0, DecimalFormat("0"), false, ok)
if (ProfileFunctions.getSystemUnits() == Constants.MMOL)
overview_temptarget_temptarget.setParams(
savedInstanceState?.getDouble("overview_temptarget_temptarget")
?: Constants.MIN_TT_MMOL,
Constants.MIN_TT_MMOL, Constants.MAX_TT_MMOL, 0.1, DecimalFormat("0.0"), false, ok)
else
overview_temptarget_temptarget.setParams(
savedInstanceState?.getDouble("overview_temptarget_temptarget")
?: Constants.MIN_TT_MGDL,
Constants.MIN_TT_MGDL, Constants.MAX_TT_MGDL, 1.0, DecimalFormat("0"), false, ok)
val units = ProfileFunctions.getSystemUnits()
overview_temptarget_units.text = if (units == Constants.MMOL) MainApp.gs(R.string.mmol) else MainApp.gs(R.string.mgdl)
// temp target
context?.let { context ->
val reasonList: List<String> = Lists.newArrayList(
MainApp.gs(R.string.manual),
MainApp.gs(R.string.cancel),
MainApp.gs(R.string.eatingsoon),
MainApp.gs(R.string.activity),
MainApp.gs(R.string.hypo)
)
val adapterReason = ArrayAdapter(context, R.layout.spinner_centered, reasonList)
overview_temptarget_reason.adapter = adapterReason
overview_temptarget_reason.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
val defaultDuration: Double
val defaultTarget: Double
when (reasonList[position]) {
MainApp.gs(R.string.eatingsoon) -> {
defaultDuration = DefaultValueHelper.determineEatingSoonTTDuration().toDouble()
defaultTarget = DefaultValueHelper.determineEatingSoonTT()
}
MainApp.gs(R.string.activity) -> {
defaultDuration = DefaultValueHelper.determineActivityTTDuration().toDouble()
defaultTarget = DefaultValueHelper.determineActivityTT()
}
MainApp.gs(R.string.hypo) -> {
defaultDuration = DefaultValueHelper.determineHypoTTDuration().toDouble()
defaultTarget = DefaultValueHelper.determineHypoTT()
}
MainApp.gs(R.string.cancel) -> {
defaultDuration = 0.0
defaultTarget = 0.0
}
else -> {
defaultDuration = overview_temptarget_duration.value
defaultTarget = overview_temptarget_temptarget.value
}
}
overview_temptarget_temptarget.value = defaultTarget
overview_temptarget_duration.value = defaultDuration
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
}
}
override fun submit(): Boolean {
val actions: LinkedList<String> = LinkedList()
val reason = overview_temptarget_reason.selectedItem.toString()
val unitResId = if (ProfileFunctions.getSystemUnits() == Constants.MGDL) R.string.mgdl else R.string.mmol
val target = overview_temptarget_temptarget.value
val duration = overview_temptarget_duration.value
if (target != 0.0 && duration != 0.0) {
actions.add(MainApp.gs(R.string.reason) + ": " + reason)
actions.add(MainApp.gs(R.string.nsprofileview_target_label) + ": " + Profile.toCurrentUnitsString(target) + " " + MainApp.gs(unitResId))
actions.add(MainApp.gs(R.string.duration) + ": " + MainApp.gs(R.string.format_hours, duration))
} else {
actions.add(MainApp.gs(R.string.stoptemptarget))
}
if (eventTimeChanged)
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(eventTime))
activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.careportal_temporarytarget), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
if (target == 0.0 || duration == 0.0) {
val tempTarget = TempTarget()
.date(eventTime)
.duration(0)
.low(0.0).high(0.0)
.source(Source.USER)
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
} else {
val tempTarget = TempTarget()
.date(eventTime)
.duration(duration.toInt())
.reason(reason)
.source(Source.USER)
.low(Profile.toMgdl(target, ProfileFunctions.getSystemUnits()))
.high(Profile.toMgdl(target, ProfileFunctions.getSystemUnits()))
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget)
}
if (duration == 10.0) SP.putBoolean(R.string.key_objectiveusetemptarget, true)
})
}
return true
}
}

View file

@ -0,0 +1,132 @@
package info.nightscout.androidaps.dialogs
import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.google.common.base.Joiner
import info.nightscout.androidaps.MainApp
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.data.DetailedBolusInfo
import info.nightscout.androidaps.db.CareportalEvent
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.interfaces.Constraint
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.DecimalFormatter
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.OKDialog
import info.nightscout.androidaps.utils.SafeParse
import info.nightscout.androidaps.utils.ToastUtils
import kotlinx.android.synthetic.main.dialog_treatment.*
import kotlinx.android.synthetic.main.okcancel.*
import java.text.DecimalFormat
import java.util.*
import kotlin.math.abs
class TreatmentDialog : DialogFragmentWithDate() {
private var maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value().toDouble()
private var maxInsulin = MainApp.getConstraintChecker().maxBolusAllowed.value()
private val textWatcher: TextWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
validateInputs()
}
}
private fun validateInputs() {
if (SafeParse.stringToInt(overview_treatment_carbs.text) > maxCarbs) {
overview_treatment_carbs.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.carbsconstraintapplied))
}
if (SafeParse.stringToDouble(overview_treatment_insulin.text) > maxInsulin) {
overview_treatment_insulin.value = 0.0
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.bolusconstraintapplied))
}
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("overview_treatment_carbs", overview_treatment_carbs.value)
savedInstanceState.putDouble("overview_treatment_insulin", overview_treatment_insulin.value)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
onCreateViewGeneral()
return inflater.inflate(R.layout.dialog_treatment, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription ?: return
overview_treatment_carbs.setParams(savedInstanceState?.getDouble("overview_treatment_carbs")
?: 0.0, 0.0, maxCarbs, 1.0, DecimalFormat("0"), false, ok, textWatcher)
overview_treatment_insulin.setParams(savedInstanceState?.getDouble("overview_treatment_insulin")
?: 0.0, 0.0, maxInsulin, pumpDescription.bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, ok, textWatcher)
}
override fun submit(): Boolean {
val pumpDescription = ConfigBuilderPlugin.getPlugin().activePump?.pumpDescription
?: return false
val insulin = SafeParse.stringToDouble(overview_treatment_insulin.text)
val carbs = SafeParse.stringToInt(overview_treatment_carbs.text)
val recordOnlyChecked = overview_treatment_record_only.isChecked
val actions: LinkedList<String?> = LinkedList()
val insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(Constraint(insulin)).value()
val carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(Constraint(carbs)).value()
if (insulinAfterConstraints > 0) {
actions.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.bolus) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + MainApp.gs(R.string.insulin_unit_shortname) + "</font>")
if (recordOnlyChecked)
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.bolusrecordedonly) + "</font>")
if (abs(insulinAfterConstraints - insulin) > pumpDescription.pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints))
}
if (carbsAfterConstraints > 0) {
actions.add(MainApp.gs(R.string.carbs) + ": " + "<font color='" + MainApp.gc(R.color.carbs) + "'>" + MainApp.gs(R.string.format_carbs, carbsAfterConstraints) + "</font>")
if (carbsAfterConstraints != carbs)
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.carbsconstraintapplied) + "</font>")
}
if (insulinAfterConstraints > 0 || carbsAfterConstraints > 0) {
activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.overview_treatment_label), HtmlHelper.fromHtml(Joiner.on("<br/>").join(actions)), Runnable {
val detailedBolusInfo = DetailedBolusInfo()
if (insulinAfterConstraints == 0.0) detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION
if (carbsAfterConstraints == 0) detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS
detailedBolusInfo.insulin = insulinAfterConstraints
detailedBolusInfo.carbs = carbsAfterConstraints.toDouble()
detailedBolusInfo.context = context
detailedBolusInfo.source = Source.USER
if (!(recordOnlyChecked && (detailedBolusInfo.insulin > 0 || pumpDescription.storesCarbInfo))) {
ConfigBuilderPlugin.getPlugin().commandQueue.bolus(detailedBolusInfo, object : Callback() {
override fun run() {
if (!result.success) {
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment)
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
MainApp.instance().startActivity(i)
}
}
})
} else
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false)
})
}
} else
activity?.let { activity ->
OKDialog.show(activity, MainApp.gs(R.string.overview_treatment_label), MainApp.gs(R.string.no_action_selected))
}
return true
}
}

View file

@ -1,10 +1,13 @@
package info.nightscout.androidaps.plugins.general.overview.dialogs
package info.nightscout.androidaps.dialogs
import android.content.Context
import android.os.Bundle
import android.text.Editable
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.OnItemSelectedListener
import android.widget.ArrayAdapter
@ -26,7 +29,7 @@ import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.*
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.overview_wizard_dialog.*
import kotlinx.android.synthetic.main.dialog_wizard.*
import org.slf4j.LoggerFactory
import java.text.DecimalFormat
import java.util.*
@ -36,16 +39,13 @@ class WizardDialog : DialogFragment() {
private val log = LoggerFactory.getLogger(WizardDialog::class.java)
private var wizard: BolusWizard? = null
private var parentContext: Context? = null
//one shot guards
private var okClicked: Boolean = false
private val textWatcher = object : TextWatcher {
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
calculateInsulin()
}
@ -53,21 +53,11 @@ class WizardDialog : DialogFragment() {
private var disposable: CompositeDisposable = CompositeDisposable()
override fun onAttach(context: Context) {
super.onAttach(context)
this.parentContext = context
}
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
override fun onDetach() {
super.onDetach()
this.parentContext = null
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putDouble("treatments_wizard_bg_input", treatments_wizard_bg_input.value)
@ -83,14 +73,14 @@ class WizardDialog : DialogFragment() {
isCancelable = true
dialog?.setCanceledOnTouchOutside(false)
return inflater.inflate(R.layout.overview_wizard_dialog, container, false)
return inflater.inflate(R.layout.dialog_wizard, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
loadCheckedStates()
processCobCheckBox()
treatments_wizard_sbcheckbox.visibility = if (SP.getBoolean(R.string.key_usesuperbolus, false)) View.VISIBLE else View.GONE
treatments_wizard_notes_layout.visibility = if (SP.getBoolean(R.string.key_show_notes_entry_dialogs, false)) View.VISIBLE else View.GONE
treatments_wizard_sbcheckbox.visibility = SP.getBoolean(R.string.key_usesuperbolus, false).toVisibility()
treatments_wizard_notes_layout.visibility = SP.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility()
val maxCarbs = MainApp.getConstraintChecker().maxCarbsAllowed.value()
val maxCorrection = MainApp.getConstraintChecker().maxBolusAllowed.value()
@ -115,7 +105,7 @@ class WizardDialog : DialogFragment() {
} else {
okClicked = true
calculateInsulin()
parentContext?.let { context ->
context?.let { context ->
wizard?.confirmAndExecute(context)
}
}
@ -124,23 +114,23 @@ class WizardDialog : DialogFragment() {
// cancel button
cancel.setOnClickListener { dismiss() }
// checkboxes
treatments_wizard_bgcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
treatments_wizard_ttcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
treatments_wizard_cobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
treatments_wizard_basaliobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
treatments_wizard_bolusiobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
treatments_wizard_bgtrendcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
treatments_wizard_sbcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) }
treatments_wizard_bgcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
treatments_wizard_ttcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
treatments_wizard_cobcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
treatments_wizard_basaliobcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
treatments_wizard_bolusiobcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
treatments_wizard_bgtrendcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
treatments_wizard_sbcheckbox.setOnCheckedChangeListener(::onCheckedChanged)
val showCalc = SP.getBoolean(MainApp.gs(R.string.key_wizard_calculation_visible), false)
treatments_wizard_delimiter.visibility = if (showCalc) View.VISIBLE else View.GONE
treatments_wizard_resulttable.visibility = if (showCalc) View.VISIBLE else View.GONE
treatments_wizard_delimiter.visibility = showCalc.toVisibility()
treatments_wizard_resulttable.visibility = showCalc.toVisibility()
treatments_wizard_calculationcheckbox.isChecked = showCalc
treatments_wizard_calculationcheckbox.setOnCheckedChangeListener { _, isChecked ->
run {
SP.putBoolean(MainApp.gs(R.string.key_wizard_calculation_visible), isChecked)
treatments_wizard_delimiter.visibility = if (isChecked) View.VISIBLE else View.GONE
treatments_wizard_resulttable.visibility = if (isChecked) View.VISIBLE else View.GONE
treatments_wizard_delimiter.visibility = isChecked.toVisibility()
treatments_wizard_resulttable.visibility = isChecked.toVisibility()
}
}
// profile spinner
@ -173,7 +163,7 @@ class WizardDialog : DialogFragment() {
disposable.clear()
}
private fun onCheckedChanged(buttonView: CompoundButton) {
private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) {
saveCheckedStates()
treatments_wizard_ttcheckbox.isEnabled = treatments_wizard_bgcheckbox.isChecked && TreatmentsPlugin.getPlugin().tempTargetFromHistory != null
if (buttonView.id == treatments_wizard_cobcheckbox.id)
@ -204,7 +194,7 @@ class WizardDialog : DialogFragment() {
}
private fun initDialog() {
val profile = ProfileFunctions.getInstance().profile
val profile = ProfileFunctions.getInstance().getProfile()
val profileStore = ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile
if (profile == null || profileStore == null) {
@ -221,7 +211,6 @@ class WizardDialog : DialogFragment() {
treatments_wizard_profile.adapter = adapter
} ?: return
val units = ProfileFunctions.getSystemUnits()
treatments_wizard_bgunits.text = units
if (units == Constants.MGDL)
@ -250,7 +239,7 @@ class WizardDialog : DialogFragment() {
calculateInsulin()
treatments_wizard_percent_used.visibility = if (SP.getInt(R.string.key_boluswizard_percentage, 100) != 100) View.VISIBLE else View.GONE
treatments_wizard_percent_used.visibility = (SP.getInt(R.string.key_boluswizard_percentage, 100) != 100).toVisibility()
}
private fun calculateInsulin() {
@ -260,8 +249,8 @@ class WizardDialog : DialogFragment() {
var profileName = treatments_wizard_profile.selectedItem.toString()
val specificProfile: Profile?
if (profileName == MainApp.gs(R.string.active)) {
specificProfile = ProfileFunctions.getInstance().profile
profileName = ProfileFunctions.getInstance().profileName
specificProfile = ProfileFunctions.getInstance().getProfile()
profileName = ProfileFunctions.getInstance().getProfileName() ?: return
} else
specificProfile = profileStore.getSpecificProfile(profileName)

View file

@ -4,7 +4,6 @@ import android.os.SystemClock;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import org.jetbrains.annotations.NotNull;
@ -20,6 +19,7 @@ import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.EventConfigBuilderUpdateGui;
import info.nightscout.androidaps.queue.CommandQueue;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.SP;
/**
@ -58,20 +58,16 @@ public abstract class PluginBase {
if (allowHardwarePump || activity == null) {
performPluginSwitch(newState, type);
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage(R.string.allow_hardware_pump_text)
.setPositiveButton(R.string.yes, (dialog, id) -> {
OKDialog.showConfirmation(activity, MainApp.gs(R.string.allow_hardware_pump_text), () -> {
performPluginSwitch(newState, type);
SP.putBoolean("allow_hardware_pump", true);
if (L.isEnabled(L.PUMP))
log.debug("First time HW pump allowed!");
})
.setNegativeButton(R.string.cancel, (dialog, id) -> {
}, () -> {
RxBus.INSTANCE.send(new EventConfigBuilderUpdateGui());
if (L.isEnabled(L.PUMP))
log.debug("User does not allow switching to HW pump!");
});
builder.create().show();
}
} else {
performPluginSwitch(newState, type);

View file

@ -381,13 +381,11 @@ public class DeviceStatus {
try {
if (device != null) record.put("device", device);
if (pump != null) record.put("pump", pump);
if (suggested != null) {
JSONObject openaps = new JSONObject();
if (enacted != null) openaps.put("enacted", enacted);
if (suggested != null) openaps.put("suggested", suggested);
if (iob != null) openaps.put("iob", iob);
record.put("openaps", openaps);
}
if (uploaderBattery != 0) record.put("uploaderBattery", uploaderBattery);
if (created_at != null) record.put("created_at", created_at);
} catch (JSONException e) {

View file

@ -50,7 +50,7 @@ import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.activities.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished;
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
@ -60,7 +60,6 @@ import info.nightscout.androidaps.queue.commands.Command;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.ToastUtils;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;

View file

@ -2,11 +2,16 @@ package info.nightscout.androidaps.plugins.configBuilder;
import androidx.annotation.Nullable;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.Lazy;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventAppInitialized;
@ -22,6 +27,7 @@ import info.nightscout.androidaps.interfaces.SensitivityInterface;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.insulin.InsulinOrefRapidActingPlugin;
import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin;
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin;
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
@ -31,14 +37,20 @@ import info.nightscout.androidaps.utils.SP;
/**
* Created by mike on 05.08.2016.
*/
@Singleton
public class ConfigBuilderPlugin extends PluginBase {
private Logger log = LoggerFactory.getLogger(L.CONFIGBUILDER);
private static ConfigBuilderPlugin configBuilderPlugin;
/**
* @deprecated Use dagger to get an instance
*/
@Deprecated
static public ConfigBuilderPlugin getPlugin() {
if (configBuilderPlugin == null)
configBuilderPlugin = new ConfigBuilderPlugin();
throw new IllegalStateException("Accessing ConfigBuilder before first instantiation");
return configBuilderPlugin;
}
@ -53,7 +65,20 @@ public class ConfigBuilderPlugin extends PluginBase {
private CommandQueue commandQueue = new CommandQueue();
public ConfigBuilderPlugin() {
private Lazy<InsulinOrefRapidActingPlugin> insulinOrefRapidActingPlugin;
//TODO: inject
LocalProfilePlugin localProfilePlugin = LocalProfilePlugin.INSTANCE;
/*
* Written by Adrian:
* The ConfigBuilderPlugin.getPlugin() method is used at 333 places throughout the app.
* In order to make the transition to DI, while legacy code is still calling `getPlugin()`,
* I'd instantiate this plugin very very early on (first injected dependency in MainApp) and use
* Lazy dependencies in this constructor.
* */
@Inject
public ConfigBuilderPlugin(Lazy<InsulinOrefRapidActingPlugin> insulinOrefRapidActingPlugin) {
super(new PluginDescription()
.mainType(PluginType.GENERAL)
.fragmentClass(ConfigBuilderFragment.class.getName())
@ -64,6 +89,8 @@ public class ConfigBuilderPlugin extends PluginBase {
.shortName(R.string.configbuilder_shortname)
.description(R.string.description_config_builder)
);
this.insulinOrefRapidActingPlugin = insulinOrefRapidActingPlugin;
configBuilderPlugin = this; // TODO: only while transitioning to Dagger
}
@Override
@ -237,9 +264,10 @@ public class ConfigBuilderPlugin extends PluginBase {
return activeBgSource;
}
@Nullable
@NotNull
public ProfileInterface getActiveProfileInterface() {
return activeProfile;
if (activeProfile != null) return activeProfile;
else return localProfilePlugin;
}
@Nullable
@ -290,8 +318,8 @@ public class ConfigBuilderPlugin extends PluginBase {
pluginsInCategory = MainApp.getSpecificPluginsList(PluginType.INSULIN);
activeInsulin = (InsulinInterface) getTheOneEnabledInArray(pluginsInCategory, PluginType.INSULIN);
if (activeInsulin == null) {
activeInsulin = InsulinOrefRapidActingPlugin.getPlugin();
InsulinOrefRapidActingPlugin.getPlugin().setPluginEnabled(PluginType.INSULIN, true);
activeInsulin = insulinOrefRapidActingPlugin.get();
insulinOrefRapidActingPlugin.get().setPluginEnabled(PluginType.INSULIN, true);
if (L.isEnabled(L.CONFIGBUILDER))
log.debug("Defaulting InsulinOrefRapidActingPlugin");
}
@ -449,7 +477,7 @@ public class ConfigBuilderPlugin extends PluginBase {
if (type == PluginType.PUMP)
VirtualPumpPlugin.getPlugin().setPluginEnabled(type, true);
else if (type == PluginType.INSULIN)
InsulinOrefRapidActingPlugin.getPlugin().setPluginEnabled(type, true);
insulinOrefRapidActingPlugin.get().setPluginEnabled(type, true);
else if (type == PluginType.SENSITIVITY)
SensitivityOref0Plugin.getPlugin().setPluginEnabled(type, true);
else if (type == PluginType.PROFILE)

View file

@ -2,7 +2,11 @@ package info.nightscout.androidaps.plugins.configBuilder
import android.content.Intent
import android.view.View
import android.widget.*
import android.widget.CheckBox
import android.widget.ImageButton
import android.widget.LinearLayout
import android.widget.RadioButton
import android.widget.TextView
import info.nightscout.androidaps.R
import info.nightscout.androidaps.activities.PreferencesActivity
import info.nightscout.androidaps.events.EventRebuildTabs
@ -10,6 +14,7 @@ import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginType
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.utils.PasswordProtection
import info.nightscout.androidaps.utils.toVisibility
class PluginViewHolder internal constructor(private val fragment: ConfigBuilderFragment,
private val pluginType: PluginType,
@ -56,8 +61,8 @@ class PluginViewHolder internal constructor(private val fragment: ConfigBuilderF
}
fun update() {
enabledExclusive.visibility = if (areMultipleSelectionsAllowed(pluginType)) View.GONE else View.VISIBLE
enabledInclusive.visibility = if (areMultipleSelectionsAllowed(pluginType)) View.VISIBLE else View.GONE
enabledExclusive.visibility = areMultipleSelectionsAllowed(pluginType).not().toVisibility()
enabledInclusive.visibility = areMultipleSelectionsAllowed(pluginType).toVisibility()
enabledExclusive.isChecked = plugin.isEnabled(pluginType)
enabledInclusive.isChecked = plugin.isEnabled(pluginType)
enabledInclusive.isEnabled = !plugin.pluginDescription.alwaysEnabled
@ -70,7 +75,7 @@ class PluginViewHolder internal constructor(private val fragment: ConfigBuilderF
pluginDescription.text = plugin.description
}
pluginPreferences.visibility = if (plugin.preferencesId == -1 || !plugin.isEnabled(pluginType)) View.INVISIBLE else View.VISIBLE
pluginVisibility.visibility = if (plugin.hasFragment()) View.VISIBLE else View.INVISIBLE
pluginVisibility.visibility = plugin.hasFragment().toVisibility()
pluginVisibility.isEnabled = !(plugin.pluginDescription.neverVisible || plugin.pluginDescription.alwaysVisible) && plugin.isEnabled(pluginType)
pluginVisibility.isChecked = plugin.isFragmentVisible
}

View file

@ -0,0 +1,19 @@
package info.nightscout.androidaps.plugins.configBuilder
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.ProfileStore
import info.nightscout.androidaps.db.ProfileSwitch
interface ProfileFunction {
fun getProfileName(): String?
fun getProfileName(customized: Boolean): String
fun getProfileNameWithDuration(): String
fun getProfileName(time: Long, customized: Boolean, showRemainingTime: Boolean): String
fun isProfileValid(from: String): Boolean
fun getProfile(): Profile?
fun getUnits(): String
fun getProfile(time: Long): Profile?
fun prepareProfileSwitch(profileStore: ProfileStore, profileName: String, duration: Int, percentage: Int, timeShift: Int, date: Long): ProfileSwitch
fun doProfileSwitch(profileStore: ProfileStore, profileName: String, duration: Int, percentage: Int, timeShift: Int, date: Long)
fun doProfileSwitch(duration: Int, percentage: Int, timeShift: Int)
}

View file

@ -0,0 +1,80 @@
package info.nightscout.androidaps.plugins.configBuilder
import info.nightscout.androidaps.Constants
import info.nightscout.androidaps.R
import info.nightscout.androidaps.data.Profile
import info.nightscout.androidaps.data.ProfileStore
import info.nightscout.androidaps.db.ProfileSwitch
import info.nightscout.androidaps.db.Source
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.utils.sharedPreferences.SP
import java.security.spec.InvalidParameterSpecException
import javax.inject.Inject
import javax.inject.Singleton
class ProfileFunctionImplementation constructor(private val sp: SP) : ProfileFunction {
override fun getProfileName(): String =
getProfileName(System.currentTimeMillis(), customized = true, showRemainingTime = false)
override fun getProfileName(customized: Boolean): String =
getProfileName(System.currentTimeMillis(), customized, showRemainingTime = false)
override fun getProfileName(time: Long, customized: Boolean, showRemainingTime: Boolean): String =
ProfileFunctions.getInstance().getProfileName(time, customized, showRemainingTime)
override fun getProfileNameWithDuration(): String =
getProfileName(System.currentTimeMillis(), customized = true, showRemainingTime = true)
override fun isProfileValid(from: String): Boolean =
getProfile()?.isValid(from) ?: false
override fun getProfile(): Profile? {
return ProfileFunctions.getInstance().getProfile()
}
override fun getProfile(time: Long): Profile? =
getProfile(System.currentTimeMillis())
override fun getUnits(): String =
sp.getString(R.string.key_units, Constants.MGDL)
override fun prepareProfileSwitch(profileStore: ProfileStore, profileName: String, duration: Int, percentage: Int, timeShift: Int, date: Long): ProfileSwitch {
val profile = profileStore.getSpecificProfile(profileName)
?: throw InvalidParameterSpecException(profileName)
val profileSwitch = ProfileSwitch()
profileSwitch.date = date
profileSwitch.source = Source.USER
profileSwitch.profileName = profileName
profileSwitch.profileJson = profile.data.toString()
profileSwitch.profilePlugin = ConfigBuilderPlugin.getPlugin().activeProfileInterface::class.java.name
profileSwitch.durationInMinutes = duration
profileSwitch.isCPP = percentage != 100 || timeShift != 0
profileSwitch.timeshift = timeShift
profileSwitch.percentage = percentage
return profileSwitch
}
override fun doProfileSwitch(profileStore: ProfileStore, profileName: String, duration: Int, percentage: Int, timeShift: Int, date: Long) {
val profileSwitch = prepareProfileSwitch(profileStore, profileName, duration, percentage, timeShift, date)
TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch)
if (percentage == 90 && duration == 10)
sp.putBoolean(R.string.key_objectiveuseprofileswitch, true)
}
override fun doProfileSwitch(duration: Int, percentage: Int, timeShift: Int) {
getProfile()?.let {
val profileSwitch = ProfileSwitch()
profileSwitch.date = System.currentTimeMillis()
profileSwitch.source = Source.USER
profileSwitch.profileName = ProfileFunctions.getInstance().getProfileName(System.currentTimeMillis(), customized = false, showRemainingTime = false)
profileSwitch.profileJson = it.data.toString()
profileSwitch.profilePlugin = ConfigBuilderPlugin.getPlugin().activeProfileInterface::class.java.name
profileSwitch.durationInMinutes = duration
profileSwitch.isCPP = percentage != 100 || timeShift != 0
profileSwitch.timeshift = timeShift
profileSwitch.percentage = percentage
TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch)
}
}
}

View file

@ -7,6 +7,7 @@ import androidx.annotation.Nullable;
import com.google.firebase.analytics.FirebaseAnalytics;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -14,6 +15,7 @@ import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.activities.ErrorHelperActivity;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.ProfileSwitch;
@ -24,7 +26,6 @@ import info.nightscout.androidaps.interfaces.ProfileInterface;
import info.nightscout.androidaps.interfaces.TreatmentsInterface;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.DateUtil;
@ -33,7 +34,7 @@ import info.nightscout.androidaps.utils.SP;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
public class ProfileFunctions {
public class ProfileFunctions implements ProfileFunction {
private static Logger log = LoggerFactory.getLogger(L.PROFILE);
private CompositeDisposable disposable = new CompositeDisposable();
@ -75,18 +76,22 @@ public class ProfileFunctions {
);
}
@NotNull
public String getProfileName() {
return getProfileName(System.currentTimeMillis(), true, false);
}
@NotNull
public String getProfileName(boolean customized) {
return getProfileName(System.currentTimeMillis(), customized, false);
}
@NotNull
public String getProfileNameWithDuration() {
return getProfileName(System.currentTimeMillis(), true, true);
}
@NotNull
public String getProfileName(long time, boolean customized, boolean showRemainingTime) {
String profileName = MainApp.gs(R.string.noprofileselected);
@ -114,7 +119,7 @@ public class ProfileFunctions {
return profileName;
}
public boolean isProfileValid(String from) {
public boolean isProfileValid(@NotNull String from) {
Profile profile = getProfile();
return profile != null && profile.isValid(from);
}
@ -124,6 +129,12 @@ public class ProfileFunctions {
return getProfile(System.currentTimeMillis());
}
@NotNull
public String getUnits() {
return getSystemUnits();
}
@NotNull
public static String getSystemUnits() {
return SP.getString(R.string.key_units, Constants.MGDL);
}
@ -156,7 +167,8 @@ public class ProfileFunctions {
return null;
}
public static ProfileSwitch prepareProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift, long date) {
@NotNull
public ProfileSwitch prepareProfileSwitch(@NotNull final ProfileStore profileStore, @NotNull final String profileName, final int duration, final int percentage, final int timeShift, long date) {
ProfileSwitch profileSwitch = new ProfileSwitch();
profileSwitch.date = date;
profileSwitch.source = Source.USER;
@ -164,20 +176,20 @@ public class ProfileFunctions {
profileSwitch.profileJson = profileStore.getSpecificProfile(profileName).getData().toString();
profileSwitch.profilePlugin = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getClass().getName();
profileSwitch.durationInMinutes = duration;
profileSwitch.isCPP = percentage != 100 || timeshift != 0;
profileSwitch.timeshift = timeshift;
profileSwitch.isCPP = percentage != 100 || timeShift != 0;
profileSwitch.timeshift = timeShift;
profileSwitch.percentage = percentage;
return profileSwitch;
}
public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) {
ProfileSwitch profileSwitch = prepareProfileSwitch(profileStore, profileName, duration, percentage, timeshift, System.currentTimeMillis());
public void doProfileSwitch(@NotNull final ProfileStore profileStore, @NotNull final String profileName, final int duration, final int percentage, final int timeShift, final long date) {
ProfileSwitch profileSwitch = prepareProfileSwitch(profileStore, profileName, duration, percentage, timeShift, date);
TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch);
if (percentage == 90 && duration == 10)
SP.putBoolean(R.string.key_objectiveuseprofileswitch, true);
}
public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) {
public void doProfileSwitch(final int duration, final int percentage, final int timeShift) {
ProfileSwitch profileSwitch = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(System.currentTimeMillis());
if (profileSwitch != null) {
profileSwitch = new ProfileSwitch();
@ -187,8 +199,8 @@ public class ProfileFunctions {
profileSwitch.profileJson = getInstance().getProfile().getData().toString();
profileSwitch.profilePlugin = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getClass().getName();
profileSwitch.durationInMinutes = duration;
profileSwitch.isCPP = percentage != 100 || timeshift != 0;
profileSwitch.timeshift = timeshift;
profileSwitch.isCPP = percentage != 100 || timeShift != 0;
profileSwitch.timeshift = timeShift;
profileSwitch.percentage = percentage;
TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch);
} else {

View file

@ -285,11 +285,13 @@ class ObjectivesFragment : Fragment() {
}.start()
}
holder.unStart.setOnClickListener {
OKDialog.showConfirmation(activity, MainApp.gs(R.string.doyouwantresetstart)) {
activity?.let { activity ->
OKDialog.showConfirmation(activity, MainApp.gs(R.string.objectives), MainApp.gs(R.string.doyouwantresetstart), Runnable {
objective.startedOn = 0
scrollToCurrentObjective()
RxBus.send(EventObjectivesUpdateGui())
RxBus.send(EventSWUpdate(false))
})
}
}
holder.unFinish.setOnClickListener {
@ -320,7 +322,6 @@ class ObjectivesFragment : Fragment() {
}
}
override fun getItemCount(): Int {
return ObjectivesPlugin.objectives.size
}

View file

@ -122,9 +122,9 @@ object ObjectivesPlugin : PluginBase(PluginDescription()
SP.putLong("Objectives_" + "smb" + "_started", DateUtil.now())
SP.putLong("Objectives_" + "smb" + "_accomplished", DateUtil.now())
setupObjectives()
OKDialog.show(activity, "", MainApp.gs(R.string.codeaccepted), null)
OKDialog.show(activity, MainApp.gs(R.string.objectives), MainApp.gs(R.string.codeaccepted))
} else {
OKDialog.show(activity, "", MainApp.gs(R.string.codeinvalid), null)
OKDialog.show(activity, MainApp.gs(R.string.objectives), MainApp.gs(R.string.codeinvalid))
}
}

View file

@ -14,7 +14,7 @@ import info.nightscout.androidaps.plugins.constraints.objectives.events.EventNtp
import info.nightscout.androidaps.utils.FabricPrivacy
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.overview_bolusprogress_dialog.*
import kotlinx.android.synthetic.main.dialog_bolusprogress.*
import org.slf4j.LoggerFactory
class NtpProgressDialog : DialogFragment() {
@ -33,16 +33,17 @@ class NtpProgressDialog : DialogFragment() {
state = savedInstanceState?.getString("state", DEFAULT_STATE) ?: DEFAULT_STATE
percent = savedInstanceState?.getInt("percent", 0) ?: 0
return inflater.inflate(R.layout.overview_bolusprogress_dialog, container, false)
return inflater.inflate(R.layout.dialog_bolusprogress, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
overview_bolusprogress_stop.setOnClickListener { dismiss() }
overview_bolusprogress_status.setText(state)
overview_bolusprogress_progressbar.setMax(100)
overview_bolusprogress_progressbar.setProgress(percent)
overview_bolusprogress_status.text = state
overview_bolusprogress_progressbar.max = 100
overview_bolusprogress_progressbar.progress = percent
overview_bolusprogress_stop.text = MainApp.gs(R.string.close)
overview_bolusprogress_title.text = MainApp.gs(R.string.please_wait)
}
override fun onResume() {

View file

@ -7,6 +7,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.MainApp
@ -18,17 +19,25 @@ import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions
import info.nightscout.androidaps.plugins.general.actions.defs.CustomAction
import info.nightscout.androidaps.plugins.general.actions.dialogs.FillDialog
import info.nightscout.androidaps.plugins.general.actions.dialogs.NewExtendedBolusDialog
import info.nightscout.androidaps.plugins.general.actions.dialogs.NewTempBasalDialog
import info.nightscout.androidaps.dialogs.CareDialog
import info.nightscout.androidaps.dialogs.ExtendedBolusDialog
import info.nightscout.androidaps.dialogs.FillDialog
import info.nightscout.androidaps.dialogs.TempBasalDialog
import info.nightscout.androidaps.plugins.general.careportal.CareportalFragment
import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog
import info.nightscout.androidaps.activities.ErrorHelperActivity
import info.nightscout.androidaps.dialogs.ProfileSwitchDialog
import info.nightscout.androidaps.dialogs.TempTargetDialog
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin
import info.nightscout.androidaps.queue.Callback
import info.nightscout.androidaps.utils.*
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.SP
import info.nightscout.androidaps.utils.SingleClickButton
import info.nightscout.androidaps.utils.plusAssign
import info.nightscout.androidaps.utils.toVisibility
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.actions_fragment.*
import kotlinx.android.synthetic.main.careportal_stats_fragment.*
import java.util.*
class ActionsFragment : Fragment() {
@ -47,39 +56,45 @@ class ActionsFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
actions_profileswitch.setOnClickListener {
val newDialog = NewNSTreatmentDialog()
val profileSwitch = CareportalFragment.PROFILESWITCH
profileSwitch.executeProfileSwitch = true
newDialog.setOptions(profileSwitch, R.string.careportal_profileswitch)
fragmentManager?.let { newDialog.show(it, "NewNSTreatmentDialog") }
fragmentManager?.let { ProfileSwitchDialog().show(it, "Actions") }
}
actions_temptarget.setOnClickListener {
val newTTDialog = NewNSTreatmentDialog()
val temptarget = CareportalFragment.TEMPTARGET
temptarget.executeTempTarget = true
newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget)
fragmentManager?.let { newTTDialog.show(it, "NewNSTreatmentDialog") }
fragmentManager?.let { TempTargetDialog().show(it, "Actions") }
}
actions_extendedbolus.setOnClickListener {
fragmentManager?.let { NewExtendedBolusDialog().show(it, "NewExtendedDialog") }
fragmentManager?.let { ExtendedBolusDialog().show(it, "Actions") }
}
actions_extendedbolus_cancel.setOnClickListener {
if (TreatmentsPlugin.getPlugin().isInHistoryExtendedBoluslInProgress) {
ConfigBuilderPlugin.getPlugin().commandQueue.cancelExtended(object : Callback() {
override fun run() {
if (!result.success)
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.extendedbolusdeliveryerror))
if (!result.success) {
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment)
i.putExtra("title", MainApp.gs(R.string.extendedbolusdeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
MainApp.instance().startActivity(i)
}
}
})
}
}
actions_settempbasal.setOnClickListener { fragmentManager?.let { NewTempBasalDialog().show(it, "NewTempDialog") } }
actions_settempbasal.setOnClickListener {
fragmentManager?.let { TempBasalDialog().show(it, "Actions") }
}
actions_canceltempbasal.setOnClickListener {
if (TreatmentsPlugin.getPlugin().isTempBasalInProgress) {
ConfigBuilderPlugin.getPlugin().commandQueue.cancelTempBasal(true, object : Callback() {
override fun run() {
if (!result.success)
ToastUtils.showToastInUiThread(MainApp.instance().applicationContext, MainApp.gs(R.string.tempbasaldeliveryerror))
if (!result.success) {
val i = Intent(MainApp.instance(), ErrorHelperActivity::class.java)
i.putExtra("soundid", R.raw.boluserror)
i.putExtra("status", result.comment)
i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
MainApp.instance().startActivity(i)
}
}
})
}
@ -87,6 +102,15 @@ class ActionsFragment : Fragment() {
actions_fill.setOnClickListener { fragmentManager?.let { FillDialog().show(it, "FillDialog") } }
actions_historybrowser.setOnClickListener { startActivity(Intent(context, HistoryBrowseActivity::class.java)) }
actions_tddstats.setOnClickListener { startActivity(Intent(context, TDDStatsActivity::class.java)) }
actions_bgcheck.setOnClickListener {
fragmentManager?.let { CareDialog().setOptions(CareDialog.EventType.BGCHECK, R.string.careportal_bgcheck).show(it, "Actions") }
}
actions_cgmsensorinsert.setOnClickListener {
fragmentManager?.let { CareDialog().setOptions(CareDialog.EventType.SENSOR_INSERT, R.string.careportal_cgmsensorinsert).show(it, "Actions") }
}
actions_pumpbatterychange.setOnClickListener {
fragmentManager?.let { CareDialog().setOptions(CareDialog.EventType.BATTERY_CHANGE, R.string.careportal_pumpbatterychange).show(it, "Actions") }
}
SP.putBoolean(R.string.key_objectiveuseactions, true)
}
@ -97,43 +121,27 @@ class ActionsFragment : Fragment() {
disposable += RxBus
.toObservable(EventInitializationChanged::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
updateGui()
}, {
FabricPrivacy.logException(it)
})
.subscribe({ updateGui() }, { FabricPrivacy.logException(it) })
disposable += RxBus
.toObservable(EventRefreshOverview::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
updateGui()
}, {
FabricPrivacy.logException(it)
})
.subscribe({ updateGui() }, { FabricPrivacy.logException(it) })
disposable += RxBus
.toObservable(EventExtendedBolusChange::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
updateGui()
}, {
FabricPrivacy.logException(it)
})
.subscribe({ updateGui() }, { FabricPrivacy.logException(it) })
disposable += RxBus
.toObservable(EventTempBasalChange::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
updateGui()
}, {
FabricPrivacy.logException(it)
})
.subscribe({ updateGui() }, { FabricPrivacy.logException(it) })
disposable += RxBus
.toObservable(EventCustomActionsChanged::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
updateGui()
}, {
FabricPrivacy.logException(it)
})
.subscribe({ updateGui() }, { FabricPrivacy.logException(it) })
disposable += RxBus
.toObservable(EventCareportalEventChange::class.java)
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ updateGui() }, { FabricPrivacy.logException(it) })
updateGui()
}
@ -149,7 +157,7 @@ class ActionsFragment : Fragment() {
if (ConfigBuilderPlugin.getPlugin().activeProfileInterface?.profile != null) View.VISIBLE
else View.GONE
if (ProfileFunctions.getInstance().profile == null) {
if (ProfileFunctions.getInstance().getProfile() == null) {
actions_temptarget?.visibility = View.GONE
actions_extendedbolus?.visibility = View.GONE
actions_extendedbolus_cancel?.visibility = View.GONE
@ -198,8 +206,11 @@ class ActionsFragment : Fragment() {
if (!pump.pumpDescription.isRefillingCapable || !pump.isInitialized || pump.isSuspended) View.GONE
else View.VISIBLE
actions_temptarget?.visibility = if (!Config.APS) View.GONE else View.VISIBLE
actions_tddstats?.visibility = if (!pump.pumpDescription.supportsTDDs) View.GONE else View.VISIBLE
actions_temptarget?.visibility = Config.APS.toVisibility()
actions_tddstats?.visibility = pump.pumpDescription.supportsTDDs.toVisibility()
activity?.let { activity ->
CareportalFragment.updateAge(activity, careportal_sensorage, careportal_insulinage, careportal_canulaage, careportal_pbage)
}
checkPumpCustomActions()
}
@ -224,8 +235,7 @@ class ActionsFragment : Fragment() {
val action = this.pumpCustomActions[b.text.toString()]
ConfigBuilderPlugin.getPlugin().activePump!!.executeCustomAction(action!!.customActionType)
}
val top = resources.getDrawable(customAction.iconResourceId)
val top = activity?.let { ContextCompat.getDrawable(it, customAction.iconResourceId) }
btn.setCompoundDrawablesWithIntrinsicBounds(null, top, null, null)
action_buttons_layout?.addView(btn)

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.general.actions
import info.nightscout.androidaps.Config
import info.nightscout.androidaps.R
import info.nightscout.androidaps.interfaces.PluginBase
import info.nightscout.androidaps.interfaces.PluginDescription
@ -8,6 +9,8 @@ import info.nightscout.androidaps.interfaces.PluginType
object ActionsPlugin : PluginBase(PluginDescription()
.mainType(PluginType.GENERAL)
.fragmentClass(ActionsFragment::class.qualifiedName)
.enableByDefault(Config.APS || Config.PUMPCONTROL)
.visibleByDefault(Config.APS || Config.PUMPCONTROL)
.pluginName(R.string.actions)
.shortName(R.string.actions_shortname)
.description(R.string.description_actions))

View file

@ -1,63 +0,0 @@
package info.nightscout.androidaps.plugins.general.actions.defs;
import info.nightscout.androidaps.R;
/**
* Created by andy on 9/20/18.
*/
public class CustomAction {
private int name;
private String iconName;
private CustomActionType customActionType;
private int iconResourceId;
private boolean enabled = true;
public CustomAction(int nameResourceId, CustomActionType actionType) {
this(nameResourceId, actionType, R.drawable.icon_actions_profileswitch, true);
}
public CustomAction(int nameResourceId, CustomActionType actionType, int iconResourceId) {
this(nameResourceId, actionType, iconResourceId, true);
}
public CustomAction(int nameResourceId, CustomActionType actionType, boolean enabled) {
this(nameResourceId, actionType, R.drawable.icon_actions_profileswitch, enabled);
}
public CustomAction(int nameResourceId, CustomActionType actionType, int iconResourceId, boolean enabled) {
this.name = nameResourceId;
this.customActionType = actionType;
this.iconResourceId = iconResourceId;
this.enabled = enabled;
}
public int getName() {
return name;
}
public CustomActionType getCustomActionType() {
return customActionType;
}
public int getIconResourceId() {
return iconResourceId;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

View file

@ -0,0 +1,10 @@
package info.nightscout.androidaps.plugins.general.actions.defs
import info.nightscout.androidaps.R
class CustomAction @JvmOverloads constructor(val name: Int, val customActionType: CustomActionType?, val iconResourceId: Int = R.drawable.icon_actions_profileswitch, var isEnabled: Boolean = true) {
constructor(nameResourceId: Int, actionType: CustomActionType?, enabled: Boolean) :
this(nameResourceId, actionType, R.drawable.icon_actions_profileswitch, enabled)
}

View file

@ -1,11 +0,0 @@
package info.nightscout.androidaps.plugins.general.actions.defs;
/**
* Created by andy on 9/20/18.
*/
public interface CustomActionType {
String getKey();
}

View file

@ -0,0 +1,5 @@
package info.nightscout.androidaps.plugins.general.actions.defs
interface CustomActionType {
val key: String?
}

View file

@ -1,255 +0,0 @@
package info.nightscout.androidaps.plugins.general.actions.dialogs;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import androidx.fragment.app.DialogFragment;
import androidx.appcompat.app.AlertDialog;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import com.google.common.base.Joiner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.LinkedList;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.NumberPicker;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.SafeParse;
import info.nightscout.androidaps.utils.ToastUtils;
import static info.nightscout.androidaps.utils.DateUtil.now;
public class FillDialog extends DialogFragment implements OnClickListener {
private static Logger log = LoggerFactory.getLogger(FillDialog.class);
private CheckBox pumpSiteChangeCheckbox;
private CheckBox insulinCartridgeChangeCheckbox;
private NumberPicker editInsulin;
double amount1 = 0d;
double amount2 = 0d;
double amount3 = 0d;
private EditText notesEdit;
//one shot guards
private boolean accepted;
private boolean okClicked;
final private TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
validateInputs();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
};
private void validateInputs() {
int time = editInsulin.getValue().intValue();
if (Math.abs(time) > 12 * 60) {
editInsulin.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.constraintapllied));
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.actions_fill_dialog, container, false);
view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this);
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
pumpSiteChangeCheckbox = view.findViewById(R.id.fill_catheter_change);
insulinCartridgeChangeCheckbox = view.findViewById(R.id.fill_cartridge_change);
Double maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
double bolusstep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep;
editInsulin = view.findViewById(R.id.fill_insulinamount);
editInsulin.setParams(0d, 0d, maxInsulin, bolusstep, DecimalFormatter.pumpSupportedBolusFormat(), false, view.findViewById(R.id.ok), textWatcher);
Button preset1Button = view.findViewById(R.id.fill_preset_button1);
amount1 = SP.getDouble("fill_button1", 0.3);
if (amount1 > 0) {
preset1Button.setVisibility(View.VISIBLE);
preset1Button.setText(DecimalFormatter.toPumpSupportedBolus(amount1)); // + "U");
preset1Button.setOnClickListener(this);
} else {
preset1Button.setVisibility(View.GONE);
}
Button preset2Button = view.findViewById(R.id.fill_preset_button2);
amount2 = SP.getDouble("fill_button2", 0d);
if (amount2 > 0) {
preset2Button.setVisibility(View.VISIBLE);
preset2Button.setText(DecimalFormatter.toPumpSupportedBolus(amount2)); // + "U");
preset2Button.setOnClickListener(this);
} else {
preset2Button.setVisibility(View.GONE);
}
Button preset3Button = view.findViewById(R.id.fill_preset_button3);
amount3 = SP.getDouble("fill_button3", 0d);
if (amount3 > 0) {
preset3Button.setVisibility(View.VISIBLE);
preset3Button.setText(DecimalFormatter.toPumpSupportedBolus(amount3)); // + "U");
preset3Button.setOnClickListener(this);
} else {
preset3Button.setVisibility(View.GONE);
}
LinearLayout notesLayout = view.findViewById(R.id.fill_notes_layout);
notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE);
notesEdit = view.findViewById(R.id.fill_notes);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.ok:
confirmAndDeliver();
break;
case R.id.cancel:
dismiss();
break;
case R.id.fill_preset_button1:
editInsulin.setValue(amount1);
break;
case R.id.fill_preset_button2:
editInsulin.setValue(amount2);
break;
case R.id.fill_preset_button3:
editInsulin.setValue(amount3);
break;
}
}
private synchronized void confirmAndDeliver() {
if (okClicked) {
log.debug("guarding: ok already clicked");
dismiss();
return;
}
okClicked = true;
try {
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
List<String> confirmMessage = new LinkedList<>();
Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value();
if (insulinAfterConstraints > 0) {
confirmMessage.add(MainApp.gs(R.string.fillwarning));
confirmMessage.add("");
confirmMessage.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.colorCarbsButton) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + "</font>");
if (Math.abs(insulinAfterConstraints - insulin) > 0.01d)
confirmMessage.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints));
}
if (pumpSiteChangeCheckbox.isChecked())
confirmMessage.add("" + "<font color='" + MainApp.gc(R.color.actionsConfirm) + "'>" + MainApp.gs(R.string.record_pump_site_change) + "</font>");
if (insulinCartridgeChangeCheckbox.isChecked())
confirmMessage.add("" + "<font color='" + MainApp.gc(R.color.actionsConfirm) + "'>" + MainApp.gs(R.string.record_insulin_cartridge_change) + "</font>");
final String notes = notesEdit.getText().toString();
if (!notes.isEmpty()) {
confirmMessage.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes);
}
final Double finalInsulinAfterConstraints = insulinAfterConstraints;
final Context context = getContext();
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation));
if (insulinAfterConstraints > 0 || pumpSiteChangeCheckbox.isChecked() || insulinCartridgeChangeCheckbox.isChecked()) {
builder.setMessage(Html.fromHtml(Joiner.on("<br/>").join(confirmMessage)));
builder.setPositiveButton(MainApp.gs(R.string.primefill), (dialog, id) -> {
synchronized (builder) {
if (accepted) {
log.debug("guarding: already accepted");
return;
}
accepted = true;
if (finalInsulinAfterConstraints > 0) {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER;
detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history)
detailedBolusInfo.notes = notes;
ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override
public void run() {
if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
});
}
if (pumpSiteChangeCheckbox.isChecked())
NSUpload.uploadEvent(CareportalEvent.SITECHANGE, now(), notes);
if (insulinCartridgeChangeCheckbox.isChecked())
NSUpload.uploadEvent(CareportalEvent.INSULINCHANGE, now() + 1000, notes);
}
});
} else {
builder.setMessage(MainApp.gs(R.string.no_action_selected));
}
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
dismiss();
} catch (RuntimeException e) {
log.error("Unhandled exception", e);
}
}
}

View file

@ -1,115 +0,0 @@
package info.nightscout.androidaps.plugins.general.actions.dialogs;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import androidx.fragment.app.DialogFragment;
import androidx.appcompat.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.NumberPicker;
import info.nightscout.androidaps.utils.SafeParse;
public class NewExtendedBolusDialog extends DialogFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(NewExtendedBolusDialog.class);
NumberPicker editInsulin;
NumberPicker editDuration;
public NewExtendedBolusDialog() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getDialog().setTitle(MainApp.gs(R.string.overview_extendedbolus_button));
View view = inflater.inflate(R.layout.overview_newextendedbolus_dialog, container, false);
Double maxInsulin = MainApp.getConstraintChecker().getMaxExtendedBolusAllowed().value();
editInsulin = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_insulin);
editInsulin.setParams(0d, 0d, maxInsulin, 0.1d, new DecimalFormat("0.00"), false, view.findViewById(R.id.ok));
double extendedDurationStep = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().extendedBolusDurationStep;
double extendedMaxDuration = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().extendedBolusMaxDuration;
editDuration = (NumberPicker) view.findViewById(R.id.overview_newextendedbolus_duration);
editDuration.setParams(extendedDurationStep, extendedDurationStep, extendedMaxDuration, extendedDurationStep, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.ok:
try {
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
int durationInMinutes = SafeParse.stringToInt(editDuration.getText());
String confirmMessage = MainApp.gs(R.string.setextendedbolusquestion);
Double insulinAfterConstraint = MainApp.getConstraintChecker().applyExtendedBolusConstraints(new Constraint<>(insulin)).value();
confirmMessage += " " + insulinAfterConstraint + " U ";
confirmMessage += MainApp.gs(R.string.duration) + " " + durationInMinutes + "min ?";
if (Math.abs(insulinAfterConstraint - insulin) > 0.01d)
confirmMessage += "\n" + MainApp.gs(R.string.constraintapllied);
insulin = insulinAfterConstraint;
final Double finalInsulin = insulin;
final int finalDurationInMinutes = durationInMinutes;
final Context context = getContext();
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(confirmMessage);
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
ConfigBuilderPlugin.getPlugin().getCommandQueue().extendedBolus(finalInsulin, finalDurationInMinutes, new Callback() {
@Override
public void run() {
if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
});
}
});
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
dismiss();
} catch (Exception e) {
log.error("Unhandled exception", e);
}
break;
case R.id.cancel:
dismiss();
break;
}
}
}

View file

@ -1,196 +0,0 @@
package info.nightscout.androidaps.plugins.general.actions.dialogs;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import androidx.fragment.app.DialogFragment;
import androidx.appcompat.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperActivity;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.NumberPicker;
import info.nightscout.androidaps.utils.SafeParse;
public class NewTempBasalDialog extends DialogFragment implements View.OnClickListener, RadioGroup.OnCheckedChangeListener {
private static Logger log = LoggerFactory.getLogger(NewTempBasalDialog.class);
RadioButton percentRadio;
RadioButton absoluteRadio;
RadioGroup basalTypeRadioGroup;
LinearLayout typeSelectorLayout;
LinearLayout percentLayout;
LinearLayout absoluteLayout;
NumberPicker basalPercent;
NumberPicker basalAbsolute;
NumberPicker duration;
public NewTempBasalDialog() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getDialog().setTitle(MainApp.gs(R.string.overview_tempbasal_button));
View view = inflater.inflate(R.layout.overview_newtempbasal_dialog, container, false);
percentLayout = (LinearLayout) view.findViewById(R.id.overview_newtempbasal_percent_layout);
absoluteLayout = (LinearLayout) view.findViewById(R.id.overview_newtempbasal_absolute_layout);
percentRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_percent_radio);
basalTypeRadioGroup = (RadioGroup) view.findViewById(R.id.overview_newtempbasal_radiogroup);
absoluteRadio = (RadioButton) view.findViewById(R.id.overview_newtempbasal_absolute_radio);
typeSelectorLayout = (LinearLayout) view.findViewById(R.id.overview_newtempbasal_typeselector_layout);
PumpDescription pumpDescription = ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription();
basalPercent = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalpercentinput);
double maxTempPercent = pumpDescription.maxTempPercent;
double tempPercentStep = pumpDescription.tempPercentStep;
basalPercent.setParams(100d, 0d, maxTempPercent, tempPercentStep, new DecimalFormat("0"), true, view.findViewById(R.id.ok));
Profile profile = ProfileFunctions.getInstance().getProfile();
Double currentBasal = profile != null ? profile.getBasal() : 0d;
basalAbsolute = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_basalabsoluteinput);
basalAbsolute.setParams(currentBasal, 0d, pumpDescription.maxTempAbsolute, pumpDescription.tempAbsoluteStep, new DecimalFormat("0.00"), true, view.findViewById(R.id.ok));
double tempDurationStep = pumpDescription.tempDurationStep;
double tempMaxDuration = pumpDescription.tempMaxDuration;
duration = (NumberPicker) view.findViewById(R.id.overview_newtempbasal_duration);
duration.setParams(tempDurationStep, tempDurationStep, tempMaxDuration, tempDurationStep, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
if ((pumpDescription.tempBasalStyle & PumpDescription.PERCENT) == PumpDescription.PERCENT && (pumpDescription.tempBasalStyle & PumpDescription.ABSOLUTE) == PumpDescription.ABSOLUTE) {
// Both allowed
typeSelectorLayout.setVisibility(View.VISIBLE);
} else {
typeSelectorLayout.setVisibility(View.GONE);
}
if ((pumpDescription.tempBasalStyle & PumpDescription.PERCENT) == PumpDescription.PERCENT) {
percentRadio.setChecked(true);
absoluteRadio.setChecked(false);
percentLayout.setVisibility(View.VISIBLE);
absoluteLayout.setVisibility(View.GONE);
} else if ((pumpDescription.tempBasalStyle & PumpDescription.ABSOLUTE) == PumpDescription.ABSOLUTE) {
percentRadio.setChecked(false);
absoluteRadio.setChecked(true);
percentLayout.setVisibility(View.GONE);
absoluteLayout.setVisibility(View.VISIBLE);
}
view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this);
basalTypeRadioGroup.setOnCheckedChangeListener(this);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.ok:
try {
int percent = 0;
Double absolute = 0d;
final boolean setAsPercent = percentRadio.isChecked();
int durationInMinutes = SafeParse.stringToInt(duration.getText());
Profile profile = ProfileFunctions.getInstance().getProfile();
if (profile == null)
return;
String confirmMessage = MainApp.gs(R.string.setbasalquestion);
if (setAsPercent) {
int basalPercentInput = SafeParse.stringToInt(basalPercent.getText());
percent = MainApp.getConstraintChecker().applyBasalPercentConstraints(new Constraint<>(basalPercentInput), profile).value();
confirmMessage += "\n" + percent + "% ";
confirmMessage += "\n" + MainApp.gs(R.string.duration) + " " + durationInMinutes + "min ?";
if (percent != basalPercentInput)
confirmMessage += "\n" + MainApp.gs(R.string.constraintapllied);
} else {
Double basalAbsoluteInput = SafeParse.stringToDouble(basalAbsolute.getText());
absolute = MainApp.getConstraintChecker().applyBasalConstraints(new Constraint<>(basalAbsoluteInput), profile).value();
confirmMessage += "\n" + absolute + " U/h ";
confirmMessage += "\n" + MainApp.gs(R.string.duration) + " " + durationInMinutes + "min ?";
if (Math.abs(absolute - basalAbsoluteInput) > 0.01d)
confirmMessage += "\n" + MainApp.gs(R.string.constraintapllied);
}
final int finalBasalPercent = percent;
final Double finalBasal = absolute;
final int finalDurationInMinutes = durationInMinutes;
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(confirmMessage);
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Callback callback = new Callback() {
@Override
public void run() {
if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.tempbasaldeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
};
if (setAsPercent) {
ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalPercent(finalBasalPercent, finalDurationInMinutes, true, profile, callback);
} else {
ConfigBuilderPlugin.getPlugin().getCommandQueue().tempBasalAbsolute(finalBasal, finalDurationInMinutes, true, profile, callback);
}
}
});
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
dismiss();
} catch (Exception e) {
log.error("Unhandled exception", e);
}
break;
case R.id.cancel:
dismiss();
break;
}
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId) {
case R.id.overview_newtempbasal_percent_radio:
percentLayout.setVisibility(View.VISIBLE);
absoluteLayout.setVisibility(View.GONE);
break;
case R.id.overview_newtempbasal_absolute_radio:
percentLayout.setVisibility(View.GONE);
absoluteLayout.setVisibility(View.VISIBLE);
break;
}
}
}

View file

@ -1,6 +1,7 @@
package info.nightscout.androidaps.plugins.general.automation
import android.os.Bundle
import android.text.method.ScrollingMovementMethod
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@ -16,12 +17,12 @@ import info.nightscout.androidaps.plugins.general.automation.dragHelpers.SimpleI
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationDataChanged
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
import info.nightscout.androidaps.utils.FabricPrivacy
import info.nightscout.androidaps.utils.HtmlHelper
import info.nightscout.androidaps.utils.plusAssign
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.automation_fragment.*
class AutomationFragment : Fragment(), OnStartDragListener {
private var disposable: CompositeDisposable = CompositeDisposable()
@ -40,6 +41,8 @@ class AutomationFragment : Fragment(), OnStartDragListener {
automation_eventListView.layoutManager = LinearLayoutManager(context)
automation_eventListView.adapter = eventListAdapter
automation_logView.setMovementMethod(ScrollingMovementMethod())
automation_fabAddEvent.setOnClickListener {
val dialog = EditEventDialog()
val args = Bundle()
@ -88,8 +91,8 @@ class AutomationFragment : Fragment(), OnStartDragListener {
eventListAdapter?.notifyDataSetChanged()
val sb = StringBuilder()
for (l in AutomationPlugin.executionLog.reversed())
sb.append(l).append("\n")
automation_logView?.text = sb.toString()
sb.append(l).append("<br>")
automation_logView?.text = HtmlHelper.fromHtml(sb.toString())
}
override fun onStartDrag(viewHolder: RecyclerView.ViewHolder) {

View file

@ -178,10 +178,10 @@ object AutomationPlugin : PluginBase(PluginDescription()
val sb = StringBuilder()
sb.append(DateUtil.timeString(DateUtil.now()))
sb.append(" ")
sb.append(if (result.success) "" else "X")
sb.append(" ")
sb.append(if (result.success) "" else "")
sb.append(" <b>")
sb.append(event.title)
sb.append(": ")
sb.append(":</b> ")
sb.append(action.shortDescription())
sb.append(": ")
sb.append(result.comment)

View file

@ -21,17 +21,29 @@ import info.nightscout.androidaps.plugins.general.automation.elements.InputProfi
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.JsonHelper;
public class ActionProfileSwitch extends Action {
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
public InputProfileName inputProfileName = new InputProfileName(ProfileFunctions.getInstance().getProfileName());
InputProfileName inputProfileName;
String profileName = "";
public ActionProfileSwitch() {
// Prevent action if active profile is already active
// but we don't have a trigger IS_NOT_EQUAL
// so check is in the doRun()
ProfileInterface profileInterface = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface();
if (profileInterface != null) {
ProfileStore profileStore = profileInterface.getProfile();
if (profileStore != null) {
String name = profileStore.getDefaultProfileName();
if (name != null) {
profileName = name;
}
}
}
inputProfileName = new InputProfileName(profileName);
}
@Override
@ -50,23 +62,43 @@ public class ActionProfileSwitch extends Action {
String activeProfileName = ProfileFunctions.getInstance().getProfileName();
//Check for uninitialized profileName
if ( profileName.equals("")){ profileName = activeProfileName; }
if ( profileName.equals("")){
log.error("Selected profile not initialized");
if (callback != null)
callback.result(new PumpEnactResult().success(false).comment(R.string.error_field_must_not_be_empty)).run();
return;
}
if ( ProfileFunctions.getInstance().getProfile() == null){
log.error("ProfileFunctions not initialized");
if (callback != null)
callback.result(new PumpEnactResult().success(false).comment(R.string.noprofile)).run();
return;
}
if (profileName.equals(activeProfileName)) {
// Profile is already switched
if (L.isEnabled(L.AUTOMATION))
log.debug("Profile is already switched");
if (callback != null)
callback.result(new PumpEnactResult().success(true).comment(R.string.alreadyset)).run();
return;
}
ProfileInterface activeProfile = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface();
if (activeProfile == null) return;
if (activeProfile == null) {
log.error("ProfileInterface not initialized");
if (callback != null)
callback.result(new PumpEnactResult().success(false).comment(R.string.noprofile)).run();
return;
}
ProfileStore profileStore = activeProfile.getProfile();
if (profileStore == null) return;
if(profileStore.getSpecificProfile(profileName) == null) {
if (L.isEnabled(L.AUTOMATION))
log.error("Selected profile does not exist! - "+ profileName);
if (callback != null)
callback.result(new PumpEnactResult().success(false).comment(R.string.notexists)).run();
return;
}
ProfileFunctions.doProfileSwitch(profileStore, profileName, 0, 100, 0);
ProfileFunctions.getInstance().doProfileSwitch(profileStore, profileName, 0, 100, 0, DateUtil.now());
if (callback != null)
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
}

View file

@ -47,7 +47,7 @@ public class ActionProfileSwitchPercent extends Action {
@Override
public void doAction(Callback callback) {
ProfileFunctions.doProfileSwitch((int) duration.getValue(), (int) pct.getValue(), 0);
ProfileFunctions.getInstance().doProfileSwitch((int) duration.getValue(), (int) pct.getValue(), 0);
if (callback != null)
callback.result(new PumpEnactResult().success(true).comment(R.string.ok)).run();
}

View file

@ -9,10 +9,11 @@ import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.general.automation.elements.InputString;
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
@ -25,6 +26,14 @@ public class ActionSendSMS extends Action {
public InputString text = new InputString();
@Inject
SmsCommunicatorPlugin smsCommunicatorPlugin;
public ActionSendSMS() {
super();
MainApp.instance().androidInjector().inject(this); // TODO inject or pass itno constructor once AutomationPlugin is prepared for Dagger
}
@Override
public int friendlyName() {
return R.string.sendsmsactiondescription;
@ -37,7 +46,7 @@ public class ActionSendSMS extends Action {
@Override
public void doAction(Callback callback) {
boolean result = SmsCommunicatorPlugin.INSTANCE.sendNotificationToAllNumbers(text.getValue());
boolean result = smsCommunicatorPlugin.sendNotificationToAllNumbers(text.getValue());
if (callback != null)
callback.result(new PumpEnactResult().success(result).comment(result ? R.string.ok : R.string.danar_error)).run();

View file

@ -75,7 +75,7 @@ public class ActionStartTempTarget extends Action {
int unitResId = value.getUnits().equals(Constants.MGDL) ? R.string.mgdl : R.string.mmol;
new LayoutBuilder()
.add(new LabelWithElement(MainApp.gs(R.string.careportal_temporarytarget) + " [" + MainApp.gs(unitResId) + "]", "", value))
.add(new LabelWithElement(MainApp.gs(R.string.careportal_temporarytarget) + "\n[" + MainApp.gs(unitResId) + "]", "", value))
.add(new LabelWithElement(MainApp.gs(R.string.careportal_newnstreatment_duration_min_label), "", duration))
.build(root);
}

View file

@ -32,7 +32,7 @@ class ActionListAdapter(private val fragmentManager: FragmentManager, private va
class ViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
fun bind(action: Action, fragmentManager: FragmentManager, recyclerView: RecyclerView.Adapter<ViewHolder>, position : Int, actionList: MutableList<Action>) {
fun bind(action: Action, fragmentManager: FragmentManager, recyclerView: RecyclerView.Adapter<ViewHolder>, position: Int, actionList: MutableList<Action>) {
view.findViewById<LinearLayout>(R.id.automation_layoutText).setOnClickListener {
if (action.hasDialog()) {
val args = Bundle()
@ -48,6 +48,7 @@ class ActionListAdapter(private val fragmentManager: FragmentManager, private va
recyclerView.notifyDataSetChanged()
RxBus.send(EventAutomationUpdateGui())
}
if (action.icon().isPresent) view.findViewById<ImageView>(R.id.automation_action_image).setImageResource(action.icon().get())
view.findViewById<TextView>(R.id.automation_viewActionTitle).text = action.shortDescription()
}
}

View file

@ -5,19 +5,18 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RadioButton
import androidx.fragment.app.DialogFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
import info.nightscout.androidaps.plugins.general.automation.actions.Action
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationAddAction
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateGui
import kotlinx.android.synthetic.main.automation_dialog_choose_action.*
import kotlinx.android.synthetic.main.okcancel.*
class ChooseActionDialog : DialogFragment() {
class ChooseActionDialog : DialogFragmentWithDate() {
var checkedIndex = -1
private var checkedIndex = -1
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
@ -26,7 +25,7 @@ class ChooseActionDialog : DialogFragment() {
checkedIndex = bundle.getInt("checkedIndex")
}
dialog?.setCanceledOnTouchOutside(false)
onCreateViewGeneral()
return inflater.inflate(R.layout.automation_dialog_choose_action, container, false)
}
@ -42,27 +41,19 @@ class ChooseActionDialog : DialogFragment() {
if (checkedIndex != -1)
(automation_radioGroup.getChildAt(checkedIndex) as RadioButton).isChecked = true
}
// OK button
ok.setOnClickListener {
dismiss()
override fun submit(): Boolean {
instantiateAction()?.let {
RxBus.send(EventAutomationAddAction(it))
RxBus.send(EventAutomationUpdateGui())
}
return true
}
// Cancel button
cancel.setOnClickListener { dismiss() }
}
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
override fun onSaveInstanceState(bundle: Bundle) {
bundle.putInt("checkedIndex", determineCheckedIndex())
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putInt("checkedIndex", determineCheckedIndex())
}
private fun instantiateAction(): Action? {
@ -86,5 +77,4 @@ class ChooseActionDialog : DialogFragment() {
}
return -1
}
}

View file

@ -5,17 +5,15 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RadioButton
import androidx.fragment.app.DialogFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
import kotlinx.android.synthetic.main.automation_dialog_choose_trigger.*
import kotlinx.android.synthetic.main.okcancel.*
class ChooseTriggerDialog : DialogFragment() {
class ChooseTriggerDialog : DialogFragmentWithDate() {
private var checkedIndex = -1
private var clickListener: OnClickListener? = null
interface OnClickListener {
@ -29,7 +27,7 @@ class ChooseTriggerDialog : DialogFragment() {
checkedIndex = bundle.getInt("checkedIndex")
}
dialog?.setCanceledOnTouchOutside(false)
onCreateViewGeneral()
return inflater.inflate(R.layout.automation_dialog_choose_trigger, container, false)
}
@ -45,30 +43,22 @@ class ChooseTriggerDialog : DialogFragment() {
if (checkedIndex != -1)
(automation_chooseTriggerRadioGroup.getChildAt(checkedIndex) as RadioButton).isChecked = true
}
// OK button
ok.setOnClickListener {
dismiss()
override fun submit(): Boolean {
instantiateTrigger()?.let {
clickListener?.onClick(it)
}
}
// Cancel button
cancel.setOnClickListener { dismiss() }
}
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
return true
}
fun setOnClickListener(clickListener: OnClickListener) {
this.clickListener = clickListener
}
override fun onSaveInstanceState(bundle: Bundle) {
bundle.putInt("checkedIndex", determineCheckedIndex())
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putInt("checkedIndex", determineCheckedIndex())
}
private fun instantiateTrigger(): Trigger? {
@ -92,5 +82,4 @@ class ChooseTriggerDialog : DialogFragment() {
}
return -1
}
}

View file

@ -4,16 +4,15 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.automation.actions.Action
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateAction
import kotlinx.android.synthetic.main.automation_dialog_action.*
import kotlinx.android.synthetic.main.okcancel.*
import org.json.JSONObject
class EditActionDialog : DialogFragment() {
class EditActionDialog : DialogFragmentWithDate() {
private var action: Action? = null
private var actionPosition: Int = -1
@ -24,8 +23,7 @@ class EditActionDialog : DialogFragment() {
actionPosition = bundle.getInt("actionPosition", -1)
bundle.getString("action")?.let { action = Action.instantiate(JSONObject(it)) }
}
dialog?.setCanceledOnTouchOutside(false)
onCreateViewGeneral()
return inflater.inflate(R.layout.automation_dialog_action, container, false)
}
@ -37,29 +35,20 @@ class EditActionDialog : DialogFragment() {
automation_editActionLayout.removeAllViews()
it.generateDialog(automation_editActionLayout)
}
}
// OK button
ok.setOnClickListener {
dismiss()
override fun submit(): Boolean {
action?.let {
RxBus.send(EventAutomationUpdateAction(it, actionPosition))
}
return true
}
// Cancel button
cancel.setOnClickListener { dismiss() }
}
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
override fun onSaveInstanceState(bundle: Bundle) {
super.onSaveInstanceState(bundle)
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
action?.let {
bundle.putInt("actionPosition", actionPosition)
bundle.putString("action", it.toJSON())
savedInstanceState.putInt("actionPosition", actionPosition)
savedInstanceState.putString("action", it.toJSON())
}
}
}

View file

@ -4,9 +4,9 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.LinearLayoutManager
import info.nightscout.androidaps.R
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.automation.AutomationEvent
import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin
@ -17,9 +17,8 @@ import info.nightscout.androidaps.utils.ToastUtils
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.automation_dialog_event.*
import kotlinx.android.synthetic.main.okcancel.*
class EditEventDialog : DialogFragment() {
class EditEventDialog : DialogFragmentWithDate() {
private var actionListAdapter: ActionListAdapter? = null
private var event: AutomationEvent = AutomationEvent()
@ -35,7 +34,7 @@ class EditEventDialog : DialogFragment() {
bundle.getString("event")?.let { event = AutomationEvent().fromJSON(it) }
}
dialog?.setCanceledOnTouchOutside(false)
onCreateViewGeneral()
return inflater.inflate(R.layout.automation_dialog_event, container, false)
}
@ -60,39 +59,6 @@ class EditEventDialog : DialogFragment() {
automation_addAction.setOnClickListener { fragmentManager?.let { ChooseActionDialog().show(it, "ChooseActionDialog") } }
// OK button
ok.setOnClickListener {
// check for title
val title = automation_inputEventTitle.text.toString()
if (title.isEmpty()) {
ToastUtils.showToastInUiThread(context, R.string.automation_missing_task_name)
return@setOnClickListener
}
event.title = title
// check for at least one trigger
val con = event.trigger as TriggerConnector
if (con.size() == 0) {
ToastUtils.showToastInUiThread(context, R.string.automation_missing_trigger)
return@setOnClickListener
}
// check for at least one action
if (event.actions.isEmpty()) {
ToastUtils.showToastInUiThread(context, R.string.automation_missing_action)
return@setOnClickListener
}
// store
if (position == -1)
AutomationPlugin.automationEvents.add(event)
else
AutomationPlugin.automationEvents[position] = event
dismiss()
RxBus.send(EventAutomationDataChanged())
}
// Cancel button
cancel.setOnClickListener { dismiss() }
showPreconditions()
disposable.add(RxBus
@ -137,9 +103,33 @@ class EditEventDialog : DialogFragment() {
)
}
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
override fun submit() : Boolean{
// check for title
val title = automation_inputEventTitle.text.toString()
if (title.isEmpty()) {
ToastUtils.showToastInUiThread(context, R.string.automation_missing_task_name)
return false
}
event.title = title
// check for at least one trigger
val con = event.trigger as TriggerConnector
if (con.size() == 0) {
ToastUtils.showToastInUiThread(context, R.string.automation_missing_trigger)
return false
}
// check for at least one action
if (event.actions.isEmpty()) {
ToastUtils.showToastInUiThread(context, R.string.automation_missing_action)
return false
}
// store
if (position == -1)
AutomationPlugin.automationEvents.add(event)
else
AutomationPlugin.automationEvents[position] = event
RxBus.send(EventAutomationDataChanged())
return true
}
override fun onDestroyView() {
@ -147,10 +137,10 @@ class EditEventDialog : DialogFragment() {
disposable.clear()
}
override fun onSaveInstanceState(bundle: Bundle) {
super.onSaveInstanceState(bundle)
bundle.putString("event", event.toJSON())
bundle.putInt("position", position)
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
savedInstanceState.putString("event", event.toJSON())
savedInstanceState.putInt("position", position)
}
private fun showPreconditions() {
@ -164,5 +154,4 @@ class EditEventDialog : DialogFragment() {
automation_forcedTriggerDescriptionLabel.visibility = View.GONE
}
}
}

View file

@ -4,15 +4,14 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.dialogs.DialogFragmentWithDate
import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.automation.events.EventAutomationUpdateTrigger
import info.nightscout.androidaps.plugins.general.automation.triggers.Trigger
import kotlinx.android.synthetic.main.automation_dialog_edit_trigger.*
import kotlinx.android.synthetic.main.okcancel.*
class EditTriggerDialog : DialogFragment() {
class EditTriggerDialog : DialogFragmentWithDate() {
private var trigger: Trigger? = null
@ -23,7 +22,7 @@ class EditTriggerDialog : DialogFragment() {
bundle.getString("trigger")?.let { trigger = Trigger.instantiate(it) }
}
dialog?.setCanceledOnTouchOutside(false)
onCreateViewGeneral()
return inflater.inflate(R.layout.automation_dialog_edit_trigger, container, false)
}
@ -32,24 +31,15 @@ class EditTriggerDialog : DialogFragment() {
// display root trigger
trigger?.generateDialog(automation_layoutTrigger, fragmentManager)
}
// OK button
ok.setOnClickListener {
dismiss()
override fun submit():Boolean {
trigger?.let { trigger -> RxBus.send(EventAutomationUpdateTrigger(trigger)) }
return true
}
// Cancel button
cancel.setOnClickListener { dismiss() }
}
override fun onStart() {
super.onStart()
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
}
override fun onSaveInstanceState(bundle: Bundle) {
super.onSaveInstanceState(bundle)
trigger?.let { bundle.putString("trigger", it.toJSON()) }
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
trigger?.let { savedInstanceState.putString("trigger", it.toJSON()) }
}
}

View file

@ -75,7 +75,7 @@ public class TriggerListAdapter {
private Spinner createSpinner() {
Spinner spinner = new Spinner(mContext);
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(mContext, android.R.layout.simple_spinner_item, TriggerConnector.Type.labels());
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(mContext, R.layout.spinner_centered, TriggerConnector.Type.labels());
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(spinnerArrayAdapter);
return spinner;

View file

@ -87,7 +87,7 @@ public class Comparator extends Element {
@Override
public void addToLayout(LinearLayout root) {
Spinner spinner = new Spinner(root.getContext());
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_item, Compare.labels());
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), R.layout.spinner_centered, Compare.labels());
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(spinnerArrayAdapter);
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(

View file

@ -54,7 +54,7 @@ public class ComparatorExists extends Element {
@Override
public void addToLayout(LinearLayout root) {
Spinner spinner = new Spinner(root.getContext());
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_item, Compare.labels());
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), R.layout.spinner_centered, Compare.labels());
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(spinnerArrayAdapter);
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(

View file

@ -87,7 +87,7 @@ public class InputDelta extends Element {
@Override
public void addToLayout(LinearLayout root) {
Spinner spinner = new Spinner(root.getContext());
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), android.R.layout.simple_spinner_item, DeltaType.labels());
ArrayAdapter<String> spinnerArrayAdapter = new ArrayAdapter<>(root.getContext(), R.layout.spinner_centered, DeltaType.labels());
spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(spinnerArrayAdapter);
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(

View file

@ -0,0 +1,107 @@
package info.nightscout.androidaps.plugins.general.automation.elements;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Spinner;
import androidx.annotation.StringRes;
import java.util.ArrayList;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
public class InputLocationMode extends Element {
public enum Mode {
INSIDE,
OUTSIDE,
GOING_IN,
GOING_OUT;
public @StringRes
int getStringRes() {
switch (this) {
case INSIDE:
return R.string.location_inside;
case OUTSIDE:
return R.string.location_outside;
case GOING_IN:
return R.string.location_going_in;
case GOING_OUT:
return R.string.location_going_out;
default:
return R.string.unknown;
}
}
public static List<String> labels() {
List<String> list = new ArrayList<>();
for (Mode c : Mode.values()) {
list.add(MainApp.gs(c.getStringRes()));
}
return list;
}
public Mode fromString(String wanted){
for (Mode c : Mode.values()) {
if(c.toString() == wanted)
return c;
}
return null;
}
}
private Mode mode;
public InputLocationMode() {
super();
mode = Mode.INSIDE;
}
public InputLocationMode(InputLocationMode another) {
super();
this.mode = another.mode;
}
@Override
public void addToLayout(LinearLayout root) {
ArrayAdapter<String> adapter = new ArrayAdapter<>(root.getContext(),
R.layout.spinner_centered, Mode.labels());
Spinner spinner = new Spinner(root.getContext());
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
LinearLayout.LayoutParams spinnerParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
spinnerParams.setMargins(0, MainApp.dpToPx(4), 0, MainApp.dpToPx(4));
spinner.setLayoutParams(spinnerParams);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
setValue(Mode.values()[position]);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spinner.setSelection(this.getValue().ordinal());
root.addView(spinner);
}
public Mode getValue() {
return mode;
}
public InputLocationMode setValue(Mode mode) {
this.mode = mode;
return this;
}
}

View file

@ -19,6 +19,7 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.general.automation.elements.InputButton;
import info.nightscout.androidaps.plugins.general.automation.elements.InputDouble;
import info.nightscout.androidaps.plugins.general.automation.elements.InputLocationMode;
import info.nightscout.androidaps.plugins.general.automation.elements.InputString;
import info.nightscout.androidaps.plugins.general.automation.elements.LabelWithElement;
import info.nightscout.androidaps.plugins.general.automation.elements.LayoutBuilder;
@ -28,12 +29,17 @@ import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.JsonHelper;
import info.nightscout.androidaps.utils.T;
import static info.nightscout.androidaps.plugins.general.automation.elements.InputLocationMode.Mode.*;
public class TriggerLocation extends Trigger {
private static Logger log = LoggerFactory.getLogger(L.AUTOMATION);
InputDouble latitude = new InputDouble(0d, -90d, +90d, 0.000001d, new DecimalFormat("0.000000"));
InputDouble longitude = new InputDouble(0d, -180d, +180d, 0.000001d, new DecimalFormat("0.000000"));
InputDouble distance = new InputDouble(200d, 0, 100000, 10d, new DecimalFormat("0"));
InputLocationMode modeSelected = new InputLocationMode();
InputLocationMode.Mode lastMode = INSIDE;
InputString name = new InputString();
private Runnable buttonAction = () -> {
@ -54,13 +60,16 @@ public class TriggerLocation extends Trigger {
latitude = new InputDouble(triggerLocation.latitude);
longitude = new InputDouble(triggerLocation.longitude);
distance = new InputDouble(triggerLocation.distance);
modeSelected = new InputLocationMode(triggerLocation.modeSelected);
if (modeSelected.getValue() == GOING_OUT)
lastMode = OUTSIDE;
lastRun = triggerLocation.lastRun;
name = triggerLocation.name;
}
@Override
public synchronized boolean shouldRun() {
Location location = LocationService.getLastLocation();
Location location = this.getCurrentLocation();
if (location == null)
return false;
@ -72,11 +81,20 @@ public class TriggerLocation extends Trigger {
a.setLongitude(longitude.getValue());
double calculatedDistance = location.distanceTo(a);
if (calculatedDistance < distance.getValue()) {
// log.debug("Moded(current/last/wanted): "+(currentMode(calculatedDistance))+"/"+lastMode+"/"+modeSelected.getValue());
// log.debug("Distance: "+calculatedDistance + "("+distance.getValue()+")");
if ((modeSelected.getValue() == INSIDE) && (calculatedDistance <= distance.getValue()) ||
((modeSelected.getValue() == OUTSIDE) && (calculatedDistance > distance.getValue())) ||
((modeSelected.getValue() == GOING_IN) && (calculatedDistance <= distance.getValue()) && (lastMode == OUTSIDE)) ||
((modeSelected.getValue() == GOING_OUT) && (calculatedDistance > distance.getValue()) && (lastMode == INSIDE))
) {
if (L.isEnabled(L.AUTOMATION))
log.debug("Ready for execution: " + friendlyDescription());
lastMode = currentMode(calculatedDistance);
return true;
}
lastMode = currentMode(calculatedDistance); // current mode will be last mode for the next check
return false;
}
@ -90,6 +108,7 @@ public class TriggerLocation extends Trigger {
data.put("longitude", longitude.getValue());
data.put("distance", distance.getValue());
data.put("name", name.getValue());
data.put("mode", modeSelected.getValue());
data.put("lastRun", lastRun);
o.put("data", data);
} catch (JSONException e) {
@ -106,7 +125,10 @@ public class TriggerLocation extends Trigger {
longitude.setValue(JsonHelper.safeGetDouble(d, "longitude"));
distance.setValue(JsonHelper.safeGetDouble(d, "distance"));
name.setValue(JsonHelper.safeGetString(d, "name"));
lastRun = JsonHelper.safeGetLong(d, "lastRun");
modeSelected.setValue(InputLocationMode.Mode.valueOf(JsonHelper.safeGetString(d, "mode")));
if (modeSelected.getValue() == GOING_OUT)
lastMode = OUTSIDE;
lastRun = DateUtil.now(); // set lastRun to now to give the service 5 mins to get the location properly
} catch (Exception e) {
log.error("Unhandled exception", e);
}
@ -120,7 +142,7 @@ public class TriggerLocation extends Trigger {
@Override
public String friendlyDescription() {
return MainApp.gs(R.string.locationis, name.getValue());
return MainApp.gs(R.string.locationis, MainApp.gs(modeSelected.getValue().getStringRes()), " " + name.getValue());
}
@Override
@ -154,6 +176,11 @@ public class TriggerLocation extends Trigger {
return this;
}
TriggerLocation setMode(InputLocationMode.Mode value) {
modeSelected.setValue(value);
return this;
}
@Override
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
new LayoutBuilder()
@ -162,7 +189,21 @@ public class TriggerLocation extends Trigger {
.add(new LabelWithElement(MainApp.gs(R.string.latitude_short), "", latitude))
.add(new LabelWithElement(MainApp.gs(R.string.longitude_short), "", longitude))
.add(new LabelWithElement(MainApp.gs(R.string.distance_short), "", distance))
.add(new LabelWithElement(MainApp.gs(R.string.location_mode), "", modeSelected))
.add(new InputButton(MainApp.gs(R.string.currentlocation), buttonAction), LocationService.getLastLocation() != null)
.build(root);
}
// Method to return the actual mode based on the current distance
InputLocationMode.Mode currentMode(double currentDistance){
if ( currentDistance <= this.distance.getValue() )
return INSIDE;
else
return OUTSIDE;
}
static Location getCurrentLocation(){
return LocationService.getLastLocation();
}
}

View file

@ -93,7 +93,7 @@ public class TriggerTempTarget extends Trigger {
@Override
public int friendlyName() {
return R.string.temptarget;
return R.string.careportal_temporarytarget;
}
@Override
@ -124,7 +124,7 @@ public class TriggerTempTarget extends Trigger {
@Override
public void generateDialog(LinearLayout root, FragmentManager fragmentManager) {
new LayoutBuilder()
.add(new StaticLabel(R.string.temptarget))
.add(new StaticLabel(R.string.careportal_temporarytarget))
.add(comparator)
.build(root);
}

View file

@ -63,7 +63,6 @@ public class CareportalFragment extends Fragment implements View.OnClickListener
public static final OptionsToShow TEMPBASALSTART = new OptionsToShow(R.id.careportal_tempbasalstart, R.string.careportal_tempbasalstart).date().bg().duration().percent().absolute();
public static final OptionsToShow TEMPBASALEND = new OptionsToShow(R.id.careportal_tempbasalend, R.string.careportal_tempbasalend).date().bg();
public static final OptionsToShow PROFILESWITCH = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch).date().duration().profile();
public static final OptionsToShow PROFILESWITCHDIRECT = new OptionsToShow(R.id.careportal_profileswitch, R.string.careportal_profileswitch).duration().profile();
public static final OptionsToShow OPENAPSOFFLINE = new OptionsToShow(R.id.careportal_openapsoffline, R.string.careportal_openapsoffline).date().duration();
public static final OptionsToShow TEMPTARGET = new OptionsToShow(R.id.careportal_temporarytarget, R.string.careportal_temporarytarget).date().duration().tempTarget();
@ -180,7 +179,6 @@ public class CareportalFragment extends Fragment implements View.OnClickListener
newDialog.setOptions(NOTE, R.string.careportal_note);
break;
case R.id.careportal_profileswitch:
PROFILESWITCH.executeProfileSwitch = false;
newDialog.setOptions(PROFILESWITCH, R.string.careportal_profileswitch);
break;
case R.id.careportal_pumpsitechange:
@ -202,7 +200,6 @@ public class CareportalFragment extends Fragment implements View.OnClickListener
newDialog.setOptions(OPENAPSOFFLINE, R.string.careportal_openapsoffline);
break;
case R.id.careportal_temporarytarget:
TEMPTARGET.executeTempTarget = false;
newDialog.setOptions(TEMPTARGET, R.string.careportal_temporarytarget);
break;
default:
@ -222,7 +219,7 @@ public class CareportalFragment extends Fragment implements View.OnClickListener
activity.runOnUiThread(
() -> {
CareportalEvent careportalEvent;
NSSettingsStatus nsSettings = new NSSettingsStatus().getInstance();
NSSettingsStatus nsSettings = NSSettingsStatus.getInstance();
double iageUrgent = nsSettings.getExtendedWarnValue("iage", "urgent", 96);
double iageWarn = nsSettings.getExtendedWarnValue("iage", "warn", 72);

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.general.careportal;
import info.nightscout.androidaps.Config;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
@ -22,10 +23,14 @@ public class CareportalPlugin extends PluginBase {
.fragmentClass(CareportalFragment.class.getName())
.pluginName(R.string.careportal)
.shortName(R.string.careportal_shortname)
.visibleByDefault(true)
.enableByDefault(true)
.visibleByDefault(Config.NSCLIENT)
.enableByDefault(Config.NSCLIENT)
.description(R.string.description_careportal)
);
}
@Override
public boolean specialEnableCondition() {
return Config.NSCLIENT;
}
}

View file

@ -1,7 +1,6 @@
package info.nightscout.androidaps.plugins.general.careportal.Dialogs;
import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
@ -9,6 +8,8 @@ import android.text.format.DateFormat;
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.ArrayAdapter;
import android.widget.Button;
@ -18,7 +19,6 @@ import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatDialogFragment;
import androidx.fragment.app.DialogFragment;
@ -45,8 +45,6 @@ import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.careportal.OptionsToShow;
@ -58,6 +56,7 @@ import info.nightscout.androidaps.utils.DefaultValueHelper;
import info.nightscout.androidaps.utils.HardLimits;
import info.nightscout.androidaps.utils.JsonHelper;
import info.nightscout.androidaps.utils.NumberPicker;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.SafeParse;
import info.nightscout.androidaps.utils.Translator;
@ -68,7 +67,7 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
private static OptionsToShow options;
private static String event;
Profile profile;
private Profile profile;
public ProfileStore profileStore;
TextView eventTypeText;
@ -105,9 +104,10 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
private static Integer seconds = null;
public void setOptions(OptionsToShow options, int event) {
public NewNSTreatmentDialog setOptions(OptionsToShow options, int event) {
this.options = options;
this.event = MainApp.gs(event);
return this;
}
public NewNSTreatmentDialog() {
@ -122,7 +122,10 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
if (options == null) return null;
getDialog().setTitle(MainApp.gs(options.eventName));
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
setStyle(DialogFragment.STYLE_NORMAL, getTheme());
View view = inflater.inflate(R.layout.careportal_newnstreatment_dialog, container, false);
@ -200,16 +203,15 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
boolean erase = false;
String units = ProfileFunctions.getSystemUnits();
DefaultValueHelper helper = new DefaultValueHelper();
if (MainApp.gs(R.string.eatingsoon).equals(reasonList.get(position))) {
defaultDuration = helper.determineEatingSoonTTDuration();
defaultTarget = helper.determineEatingSoonTT();
defaultDuration = DefaultValueHelper.determineEatingSoonTTDuration();
defaultTarget = DefaultValueHelper.determineEatingSoonTT();
} else if (MainApp.gs(R.string.activity).equals(reasonList.get(position))) {
defaultDuration = helper.determineActivityTTDuration();
defaultTarget = helper.determineActivityTT();
defaultDuration = DefaultValueHelper.determineActivityTTDuration();
defaultTarget = DefaultValueHelper.determineActivityTT();
} else if (MainApp.gs(R.string.hypo).equals(reasonList.get(position))) {
defaultDuration = helper.determineHypoTTDuration();
defaultTarget = helper.determineHypoTT();
defaultDuration = DefaultValueHelper.determineHypoTTDuration();
defaultTarget = DefaultValueHelper.determineHypoTT();
} else if (editDuration.getValue() != 0) {
defaultDuration = editDuration.getValue();
} else {
@ -394,6 +396,13 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
return view;
}
@Override
public void onResume() {
super.onResume();
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
@Override
public void onClick(View view) {
Calendar calendar = Calendar.getInstance();
@ -585,12 +594,12 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
String buildConfirmText(JSONObject data) {
String ret = "";
if (data.has("eventType")) {
ret += MainApp.gs(R.string.careportal_newnstreatment_eventtype);
ret += ": ";
ret += Translator.translate(JsonHelper.safeGetString(data, "eventType", ""));
ret += "\n";
}
// if (data.has("eventType")) {
// ret += MainApp.gs(R.string.careportal_newnstreatment_eventtype);
// ret += ": ";
// ret += Translator.translate(JsonHelper.safeGetString(data, "eventType", ""));
// ret += "\n";
// }
if (data.has("glucose")) {
ret += MainApp.gs(R.string.treatments_wizard_bg_label);
ret += ": ";
@ -672,7 +681,7 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
ret += "\n";
}
if (data.has("created_at")) {
ret += MainApp.gs(R.string.careportal_newnstreatment_eventtime_label);
ret += MainApp.gs(R.string.event_time_label);
ret += ": ";
ret += eventTime.toLocaleString();
ret += "\n";
@ -687,50 +696,15 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
return ret;
}
void confirmNSTreatmentCreation() {
Context context = getContext();
if (context != null) {
private void confirmNSTreatmentCreation() {
final JSONObject data = gatherData();
final String confirmText = buildConfirmText(data);
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(confirmText);
builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> createNSTreatment(data));
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
}
OKDialog.showConfirmation(getContext(), Translator.translate(JsonHelper.safeGetString(data, "eventType", MainApp.gs(R.string.overview_treatment_label))), buildConfirmText(data), () -> createNSTreatment(data));
}
void createNSTreatment(JSONObject data) {
if (options.executeProfileSwitch) {
if (data.has("profile")) {
ProfileFunctions.doProfileSwitch(profileStore, JsonHelper.safeGetString(data, "profile"), JsonHelper.safeGetInt(data, "duration"), JsonHelper.safeGetInt(data, "percentage"), JsonHelper.safeGetInt(data, "timeshift"));
}
} else if (options.executeTempTarget) {
final int duration = JsonHelper.safeGetInt(data, "duration");
final double targetBottom = JsonHelper.safeGetDouble(data, "targetBottom");
final double targetTop = JsonHelper.safeGetDouble(data, "targetTop");
final String reason = JsonHelper.safeGetString(data, "reason", "");
if ((targetBottom != 0d && targetTop != 0d) || duration == 0) {
TempTarget tempTarget = new TempTarget()
.date(eventTime.getTime())
.duration(duration)
.reason(reason)
.source(Source.USER);
if (tempTarget.durationInMinutes != 0) {
tempTarget.low(Profile.toMgdl(targetBottom, ProfileFunctions.getSystemUnits()))
.high(Profile.toMgdl(targetTop, ProfileFunctions.getSystemUnits()));
} else {
tempTarget.low(0).high(0);
}
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
}
if (duration == 10)
SP.putBoolean(R.string.key_objectiveusetemptarget, true);
} else {
if (JsonHelper.safeGetString(data, "eventType").equals(CareportalEvent.PROFILESWITCH)) {
ProfileSwitch profileSwitch = ProfileFunctions.prepareProfileSwitch(
if (JsonHelper.safeGetString(data, "eventType", "").equals(CareportalEvent.PROFILESWITCH)) {
ProfileSwitch profileSwitch = ProfileFunctions.getInstance().prepareProfileSwitch(
profileStore,
JsonHelper.safeGetString(data, "profile"),
JsonHelper.safeGetInt(data, "duration"),
@ -743,7 +717,6 @@ public class NewNSTreatmentDialog extends AppCompatDialogFragment implements Vie
NSUpload.uploadCareportalEntryToNS(data);
}
}
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {

View file

@ -19,10 +19,6 @@ public class OptionsToShow {
public boolean split;
public boolean tempTarget;
// perform direct actions
public boolean executeProfileSwitch = false;
public boolean executeTempTarget = false;
public OptionsToShow(int eventType, int eventName) {
this.eventType = eventType;
this.eventName = eventName;

View file

@ -1,6 +1,5 @@
package info.nightscout.androidaps.plugins.general.food;
import android.content.DialogInterface;
import android.graphics.Paint;
import android.os.Bundle;
import android.text.Editable;
@ -14,14 +13,11 @@ import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@ -33,6 +29,7 @@ import info.nightscout.androidaps.events.EventFoodDatabaseChanged;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.SpinnerHelper;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
@ -42,43 +39,36 @@ import io.reactivex.disposables.CompositeDisposable;
*/
public class FoodFragment extends Fragment {
private static Logger log = LoggerFactory.getLogger(FoodFragment.class);
private CompositeDisposable disposable = new CompositeDisposable();
EditText filter;
ImageView clearFilter;
SpinnerHelper category;
SpinnerHelper subcategory;
RecyclerView recyclerView;
private EditText filter;
private SpinnerHelper category;
private SpinnerHelper subcategory;
private RecyclerView recyclerView;
List<Food> unfiltered;
List<Food> filtered;
ArrayList<CharSequence> categories;
ArrayList<CharSequence> subcategories;
private List<Food> unfiltered;
private List<Food> filtered;
final String EMPTY = MainApp.gs(R.string.none);
private final String EMPTY = MainApp.gs(R.string.none);
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.food_fragment, container, false);
filter = (EditText) view.findViewById(R.id.food_filter);
clearFilter = (ImageView) view.findViewById(R.id.food_clearfilter);
filter = view.findViewById(R.id.food_filter);
ImageView clearFilter = view.findViewById(R.id.food_clearfilter);
category = new SpinnerHelper(view.findViewById(R.id.food_category));
subcategory = new SpinnerHelper(view.findViewById(R.id.food_subcategory));
recyclerView = (RecyclerView) view.findViewById(R.id.food_recyclerview);
recyclerView = view.findViewById(R.id.food_recyclerview);
recyclerView.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(view.getContext());
recyclerView.setLayoutManager(llm);
clearFilter.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clearFilter.setOnClickListener(v -> {
filter.setText("");
category.setSelection(0);
subcategory.setSelection(0);
filterData();
}
});
category.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@ -149,11 +139,11 @@ public class FoodFragment extends Fragment {
disposable.clear();
}
void loadData() {
private void loadData() {
unfiltered = FoodPlugin.getPlugin().getService().getFoodData();
}
void fillCategories() {
private void fillCategories() {
Set<CharSequence> catSet = new HashSet<>();
for (Food f : unfiltered) {
@ -162,7 +152,7 @@ public class FoodFragment extends Fragment {
}
// make it unique
categories = new ArrayList<>(catSet);
ArrayList<CharSequence> categories = new ArrayList<>(catSet);
categories.add(0, MainApp.gs(R.string.none));
ArrayAdapter<CharSequence> adapterCategories = new ArrayAdapter<>(getContext(),
@ -170,7 +160,7 @@ public class FoodFragment extends Fragment {
category.setAdapter(adapterCategories);
}
void fillSubcategories() {
private void fillSubcategories() {
String categoryFilter = category.getSelectedItem().toString();
Set<CharSequence> subCatSet = new HashSet<>();
@ -184,7 +174,7 @@ public class FoodFragment extends Fragment {
}
// make it unique
subcategories = new ArrayList<>(subCatSet);
ArrayList<CharSequence> subcategories = new ArrayList<>(subCatSet);
subcategories.add(0, MainApp.gs(R.string.none));
ArrayAdapter<CharSequence> adapterSubcategories = new ArrayAdapter<>(getContext(),
@ -192,7 +182,7 @@ public class FoodFragment extends Fragment {
subcategory.setAdapter(adapterSubcategories);
}
void filterData() {
private void filterData() {
String textFilter = filter.getText().toString();
String categoryFilter = category.getSelectedItem().toString();
String subcategoryFilter = subcategory.getSelectedItem().toString();
@ -227,6 +217,7 @@ public class FoodFragment extends Fragment {
this.foodList = foodList;
}
@NonNull
@Override
public FoodsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.food_item, viewGroup, false);
@ -257,7 +248,7 @@ public class FoodFragment extends Fragment {
return foodList.size();
}
class FoodsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
class FoodsViewHolder extends RecyclerView.ViewHolder {
TextView name;
TextView portion;
TextView carbs;
@ -269,43 +260,26 @@ public class FoodFragment extends Fragment {
FoodsViewHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.food_name);
portion = (TextView) itemView.findViewById(R.id.food_portion);
carbs = (TextView) itemView.findViewById(R.id.food_carbs);
fat = (TextView) itemView.findViewById(R.id.food_fat);
protein = (TextView) itemView.findViewById(R.id.food_protein);
energy = (TextView) itemView.findViewById(R.id.food_energy);
ns = (TextView) itemView.findViewById(R.id.ns_sign);
remove = (TextView) itemView.findViewById(R.id.food_remove);
remove.setOnClickListener(this);
remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
}
@Override
public void onClick(View v) {
name = itemView.findViewById(R.id.food_name);
portion = itemView.findViewById(R.id.food_portion);
carbs = itemView.findViewById(R.id.food_carbs);
fat = itemView.findViewById(R.id.food_fat);
protein = itemView.findViewById(R.id.food_protein);
energy = itemView.findViewById(R.id.food_energy);
ns = itemView.findViewById(R.id.ns_sign);
remove = itemView.findViewById(R.id.food_remove);
remove.setOnClickListener(v -> {
final Food food = (Food) v.getTag();
switch (v.getId()) {
case R.id.food_remove:
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(MainApp.gs(R.string.removerecord) + "\n" + food.name);
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
OKDialog.showConfirmation(getContext(), MainApp.gs(R.string.confirmation), MainApp.gs(R.string.removerecord) + "\n" + food.name, (dialog, id) -> {
final String _id = food._id;
if (_id != null && !_id.equals("")) {
NSUpload.removeFoodFromNS(_id);
}
FoodPlugin.getPlugin().getService().delete(food);
}
}, null);
});
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
break;
remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
}
}
}
}
}

View file

@ -2,15 +2,14 @@ package info.nightscout.androidaps.plugins.general.maintenance;
import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.preference.PreferenceManager;
import androidx.core.app.ActivityCompat;
import androidx.fragment.app.Fragment;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -39,7 +38,7 @@ import info.nightscout.androidaps.utils.ToastUtils;
public class ImportExportPrefs {
private static Logger log = LoggerFactory.getLogger(L.CORE);
static File path = new File(Environment.getExternalStorageDirectory().toString());
private static File path = new File(Environment.getExternalStorageDirectory().toString());
static public final File file = new File(path, MainApp.gs(R.string.app_name) + "Preferences");
private static final int REQUEST_EXTERNAL_STORAGE = 1;
@ -48,21 +47,7 @@ public class ImportExportPrefs {
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
public static void verifyStoragePermissions(Activity activity) {
// Check if we have write permission
int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (permission != PackageManager.PERMISSION_GRANTED) {
// We don't have permission so prompt the user
ActivityCompat.requestPermissions(
activity,
PERMISSIONS_STORAGE,
REQUEST_EXTERNAL_STORAGE
);
}
}
public static void verifyStoragePermissions(Fragment fragment) {
static void verifyStoragePermissions(Fragment fragment) {
int permission = ContextCompat.checkSelfPermission(fragment.getContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE);
@ -73,17 +58,13 @@ public class ImportExportPrefs {
}
public static void exportSharedPreferences(final Fragment f) {
static void exportSharedPreferences(final Fragment f) {
exportSharedPreferences(f.getContext());
}
public static void exportSharedPreferences(final Context c) {
new AlertDialog.Builder(c)
.setMessage(MainApp.gs(R.string.export_to) + " " + file + " ?")
.setPositiveButton(android.R.string.yes, (dialog, which) -> {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(c);
private static void exportSharedPreferences(final Context context) {
OKDialog.showConfirmation(context, MainApp.gs(R.string.maintenance), MainApp.gs(R.string.export_to) + " " + file + " ?", () -> {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
try {
FileWriter fw = new FileWriter(file);
PrintWriter pw = new PrintWriter(fw);
@ -93,27 +74,22 @@ public class ImportExportPrefs {
}
pw.close();
fw.close();
ToastUtils.showToastInUiThread(c, MainApp.gs(R.string.exported));
ToastUtils.showToastInUiThread(context, MainApp.gs(R.string.exported));
} catch (FileNotFoundException e) {
ToastUtils.showToastInUiThread(c, MainApp.gs(R.string.filenotfound) + " " + file);
ToastUtils.showToastInUiThread(context, MainApp.gs(R.string.filenotfound) + " " + file);
log.error("Unhandled exception", e);
} catch (IOException e) {
log.error("Unhandled exception", e);
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
});
}
public static void importSharedPreferences(final Fragment fragment) {
static void importSharedPreferences(final Fragment fragment) {
importSharedPreferences(fragment.getContext());
}
public static void importSharedPreferences(final Context context) {
new AlertDialog.Builder(context)
.setMessage(MainApp.gs(R.string.import_from) + " " + file + " ?")
.setPositiveButton(android.R.string.yes, (dialog, which) -> {
OKDialog.showConfirmation(context, MainApp.gs(R.string.maintenance), MainApp.gs(R.string.import_from) + " " + file + " ?", () -> {
String line;
String[] lineParts;
try {
@ -134,11 +110,9 @@ public class ImportExportPrefs {
SP.putBoolean(R.string.key_setupwizard_processed, true);
OKDialog.show(context, MainApp.gs(R.string.setting_imported), MainApp.gs(R.string.restartingapp), () -> {
log.debug("Exiting");
MainApp.instance().stopKeepAliveService();
RxBus.INSTANCE.send(new EventAppExit());
MainApp.closeDbHelper();
if (context instanceof Activity) {
((Activity)context).finish();
((Activity) context).finish();
}
System.runFinalization();
System.exit(0);
@ -149,9 +123,6 @@ public class ImportExportPrefs {
} catch (IOException e) {
log.error("Unhandled exception", e);
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
});
}
}

View file

@ -2,81 +2,58 @@ package info.nightscout.androidaps.plugins.general.maintenance;
import android.content.Intent;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.appcompat.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.fragment.app.Fragment;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.general.food.FoodPlugin;
import info.nightscout.androidaps.plugins.general.maintenance.activities.LogSettingActivity;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.utils.OKDialog;
/**
*
*/
public class MaintenanceFragment extends Fragment {
private Fragment f;
@Override
public void onResume() {
super.onResume();
this.f = this;
}
@Override
public void onPause() {
super.onPause();
this.f = null;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.maintenance_fragment, container, false);
final Fragment f = this;
view.findViewById(R.id.log_send).setOnClickListener(view1 -> MaintenancePlugin.getPlugin().sendLogs());
view.findViewById(R.id.log_delete).setOnClickListener(view1 -> MaintenancePlugin.getPlugin().deleteLogs());
view.findViewById(R.id.nav_resetdb).setOnClickListener(view1 -> new AlertDialog.Builder(f.getContext())
.setTitle(R.string.nav_resetdb)
.setMessage(R.string.reset_db_confirm)
.setNegativeButton(android.R.string.cancel, null)
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
view.findViewById(R.id.nav_resetdb).setOnClickListener(view1 ->
OKDialog.showConfirmation(getContext(), MainApp.gs(R.string.maintenance), MainApp.gs(R.string.reset_db_confirm), () -> {
MainApp.getDbHelper().resetDatabases();
// should be handled by Plugin-Interface and
// additional service interface and plugin registry
FoodPlugin.getPlugin().getService().resetFood();
TreatmentsPlugin.getPlugin().getService().resetTreatments();
})
.create()
.show());
);
view.findViewById(R.id.nav_export).setOnClickListener(view1 -> {
// start activity for checking permissions...
ImportExportPrefs.verifyStoragePermissions(f);
ImportExportPrefs.exportSharedPreferences(f);
ImportExportPrefs.verifyStoragePermissions(this);
ImportExportPrefs.exportSharedPreferences(this);
});
view.findViewById(R.id.nav_import).setOnClickListener(view1 -> {
// start activity for checking permissions...
ImportExportPrefs.verifyStoragePermissions(f);
ImportExportPrefs.importSharedPreferences(f);
ImportExportPrefs.verifyStoragePermissions(this);
ImportExportPrefs.importSharedPreferences(this);
});
view.findViewById(R.id.nav_logsettings).setOnClickListener(view1 -> {
startActivity(new Intent(getActivity(), LogSettingActivity.class));
});
return view;
}

View file

@ -1,9 +1,6 @@
package info.nightscout.androidaps.plugins.general.nsclient;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Paint;
import android.os.Bundle;
import android.text.Html;
@ -25,6 +22,7 @@ import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientN
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.OKDialog;
import info.nightscout.androidaps.utils.SP;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
@ -113,20 +111,11 @@ public class NSClientFragment extends Fragment implements View.OnClickListener,
NSClientPlugin.getPlugin().clearLog();
break;
case R.id.nsclientinternal_clearqueue:
final Context context = getContext();
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage("Clear queue? All data in queue will be lost!");
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
OKDialog.showConfirmation(getContext(),MainApp.gs(R.string.nsclientinternal), MainApp.gs(R.string.clearqueueconfirm), () -> {
UploadQueue.clearQueue();
updateGui();
FabricPrivacy.getInstance().logCustom("NSClientClearQueue");
}
});
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
break;
case R.id.nsclientinternal_showqueue:
RxBus.INSTANCE.send(new EventNSClientNewLog("QUEUE", NSClientPlugin.getPlugin().queue().textList()));

View file

@ -32,6 +32,8 @@ import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientNewLog;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus;
import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientUpdateGUI;
@ -250,4 +252,25 @@ public class NSClientPlugin extends PluginBase {
public boolean hasWritePermission() {
return nsClientService.hasWriteAuth;
}
public void handleClearAlarm(NSAlarm originalAlarm, long silenceTimeInMsec) {
if (!isEnabled(PluginType.GENERAL)) {
return;
}
if (SP.getBoolean(R.string.key_ns_noupload, false)) {
if (L.isEnabled(L.NSCLIENT))
log.debug("Upload disabled. Message dropped");
return;
}
AlarmAck ack = new AlarmAck();
ack.level = originalAlarm.getLevel();
ack.group = originalAlarm.getGroup();
ack.silenceTime = silenceTimeInMsec;
if (nsClientService != null)
nsClientService.sendAlarmAck(ack);
}
}

View file

@ -1,14 +1,13 @@
package info.nightscout.androidaps.plugins.general.nsclient;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import androidx.annotation.Nullable;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
@ -24,22 +23,23 @@ import java.util.Locale;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.services.Intents;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.ProfileSwitch;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.aps.loop.APSResult;
import info.nightscout.androidaps.plugins.aps.loop.DeviceStatus;
import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.data.DbLogger;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin;
import info.nightscout.androidaps.utils.BatteryLevel;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.SP;
@ -53,7 +53,6 @@ public class NSUpload {
public static void uploadTempBasalStartAbsolute(TemporaryBasal temporaryBasal, Double originalExtendedAmount) {
try {
Context context = MainApp.instance().getApplicationContext();
JSONObject data = new JSONObject();
data.put("eventType", CareportalEvent.TEMPBASAL);
data.put("duration", temporaryBasal.durationInMinutes);
@ -65,15 +64,7 @@ public class NSUpload {
data.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name));
if (originalExtendedAmount != null)
data.put("originalExtendedAmount", originalExtendedAmount); // for back synchronization
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString());
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
@ -96,7 +87,6 @@ public class NSUpload {
uploadTempBasalStartAbsolute(t, null);
}
} else {
Context context = MainApp.instance().getApplicationContext();
JSONObject data = new JSONObject();
data.put("eventType", CareportalEvent.TEMPBASAL);
data.put("duration", temporaryBasal.durationInMinutes);
@ -107,15 +97,7 @@ public class NSUpload {
data.put("pumpId", temporaryBasal.pumpId);
data.put("created_at", DateUtil.toISOString(temporaryBasal.date));
data.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name));
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString());
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
@ -124,7 +106,6 @@ public class NSUpload {
public static void uploadTempBasalEnd(long time, boolean isFakedTempBasal, long pumpId) {
try {
Context context = MainApp.instance().getApplicationContext();
JSONObject data = new JSONObject();
data.put("eventType", CareportalEvent.TEMPBASAL);
data.put("created_at", DateUtil.toISOString(time));
@ -133,15 +114,7 @@ public class NSUpload {
data.put("isFakedTempBasal", isFakedTempBasal);
if (pumpId != 0)
data.put("pumpId", pumpId);
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString());
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
@ -149,7 +122,6 @@ public class NSUpload {
public static void uploadExtendedBolus(ExtendedBolus extendedBolus) {
try {
Context context = MainApp.instance().getApplicationContext();
JSONObject data = new JSONObject();
data.put("eventType", CareportalEvent.COMBOBOLUS);
data.put("duration", extendedBolus.durationInMinutes);
@ -161,15 +133,7 @@ public class NSUpload {
data.put("pumpId", extendedBolus.pumpId);
data.put("created_at", DateUtil.toISOString(extendedBolus.date));
data.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name));
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString());
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
@ -177,7 +141,6 @@ public class NSUpload {
public static void uploadExtendedBolusEnd(long time, long pumpId) {
try {
Context context = MainApp.instance().getApplicationContext();
JSONObject data = new JSONObject();
data.put("eventType", CareportalEvent.COMBOBOLUS);
data.put("duration", 0);
@ -189,15 +152,7 @@ public class NSUpload {
data.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name));
if (pumpId != 0)
data.put("pumpId", pumpId);
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString());
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
@ -246,7 +201,12 @@ public class NSUpload {
}
} else {
if (L.isEnabled(L.NSCLIENT))
log.debug("OpenAPS data too old to upload");
log.debug("OpenAPS data too old to upload, sending iob only");
IobTotal[] iob = IobCobCalculatorPlugin.getPlugin().calculateIobArrayInDia(profile);
if (iob.length > 0) {
deviceStatus.iob = iob[0].json();
deviceStatus.iob.put("time", DateUtil.toISOString(DateUtil.now()));
}
}
deviceStatus.device = "openaps://" + Build.MANUFACTURER + " " + Build.MODEL;
JSONObject pumpstatus = ConfigBuilderPlugin.getPlugin().getActivePump().getJSONStatus(profile, profileName);
@ -258,16 +218,7 @@ public class NSUpload {
deviceStatus.uploaderBattery = batteryLevel;
deviceStatus.created_at = DateUtil.toISOString(new Date());
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "devicestatus");
bundle.putString("data", deviceStatus.mongoRecord().toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, deviceStatus.mongoRecord().toString());
UploadQueue.add(new DbRequest("dbAdd", "devicestatus", deviceStatus.mongoRecord()));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
@ -333,17 +284,7 @@ public class NSUpload {
try {
JSONObject data = getJson(profileSwitch);
if (profileSwitch._id != null) {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbUpdate");
bundle.putString("collection", "treatments");
bundle.putString("data", data.toString());
bundle.putString("_id", profileSwitch._id);
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString());
UploadQueue.add(new DbRequest("dbUpdate", "treatments", profileSwitch._id, data));
}
} catch (JSONException e) {
log.error("Unhandled exception", e);
@ -382,16 +323,7 @@ public class NSUpload {
prebolus.put("created_at", DateUtil.toISOString(preBolusDate));
uploadCareportalEntryToNS(prebolus);
}
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString());
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
} catch (Exception e) {
log.error("Unhandled exception", e);
}
@ -399,40 +331,17 @@ public class NSUpload {
}
public static void removeCareportalEntryFromNS(String _id) {
try {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbRemove");
bundle.putString("collection", "treatments");
bundle.putString("_id", _id);
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbRemove(intent, _id);
} catch (Exception e) {
log.error("Unhandled exception", e);
}
UploadQueue.add(new DbRequest("dbRemove", "treatments", _id));
}
public static void uploadOpenAPSOffline(double durationInMinutes) {
try {
Context context = MainApp.instance().getApplicationContext();
JSONObject data = new JSONObject();
data.put("eventType", "OpenAPS Offline");
data.put("duration", durationInMinutes);
data.put("created_at", DateUtil.toISOString(new Date()));
data.put("enteredBy", "openaps://" + MainApp.gs(R.string.app_name));
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString());
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
@ -443,10 +352,6 @@ public class NSUpload {
}
public static void uploadError(String error, Date date) {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
JSONObject data = new JSONObject();
try {
data.put("eventType", "Announcement");
@ -457,19 +362,10 @@ public class NSUpload {
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString());
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
}
public static void uploadBg(BgReading reading, String source) {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "entries");
JSONObject data = new JSONObject();
try {
data.put("device", source);
@ -481,20 +377,11 @@ public class NSUpload {
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString());
UploadQueue.add(new DbRequest("dbAdd", "entries", data));
}
public static void uploadAppStart() {
if (SP.getBoolean(R.string.key_ns_logappstartedevent, true)) {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
JSONObject data = new JSONObject();
try {
data.put("eventType", "Note");
@ -503,35 +390,17 @@ public class NSUpload {
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString());
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
}
}
public static void uploadProfileStore(JSONObject profileStore) {
if (SP.getBoolean(R.string.key_ns_uploadlocalprofile, false)) {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "profile");
bundle.putString("data", String.valueOf(profileStore));
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, String.valueOf(profileStore));
UploadQueue.add(new DbRequest("dbAdd", "profile", String.valueOf(profileStore)));
}
}
public static void uploadEvent(String careportalEvent, long time, @Nullable String notes) {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbAdd");
bundle.putString("collection", "treatments");
JSONObject data = new JSONObject();
try {
data.put("eventType", careportalEvent);
@ -543,26 +412,12 @@ public class NSUpload {
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
bundle.putString("data", data.toString());
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbAdd(intent, data.toString());
UploadQueue.add(new DbRequest("dbAdd", "treatments", data));
}
public static void removeFoodFromNS(String _id) {
try {
Context context = MainApp.instance().getApplicationContext();
Bundle bundle = new Bundle();
bundle.putString("action", "dbRemove");
bundle.putString("collection", "food");
bundle.putString("_id", _id);
Intent intent = new Intent(Intents.ACTION_DATABASE);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
DbLogger.dbRemove(intent, _id);
UploadQueue.add(new DbRequest("dbRemove", "food", _id));
} catch (Exception e) {
log.error("Unhandled exception", e);
}

View file

@ -1,43 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient.broadcasts;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.services.Intents;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSAlarm;
import info.nightscout.androidaps.utils.SP;
/**
* Created by mike on 11.06.2017.
*/
public class BroadcastAckAlarm {
public static void handleClearAlarm(NSAlarm originalAlarm, Context context, long silenceTimeInMsec) {
Bundle bundle = new Bundle();
bundle.putInt("level", originalAlarm.getLevel());
bundle.putString("group", originalAlarm.getGroup());
bundle.putLong("silenceTime", silenceTimeInMsec);
Intent intent = new Intent(Intents.ACTION_ACK_ALARM);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent);
if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, false)) {
bundle = new Bundle();
bundle.putInt("level", originalAlarm.getLevel());
bundle.putString("group", originalAlarm.getGroup());
bundle.putLong("silenceTime", silenceTimeInMsec);
intent = new Intent(Intents.ACTION_ACK_ALARM);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
context.sendBroadcast(intent);
}
}
}

View file

@ -25,12 +25,11 @@ import info.nightscout.androidaps.utils.SP;
public class BroadcastTreatment {
private static Logger log = LoggerFactory.getLogger(L.NSCLIENT);
public static void handleNewTreatment(JSONObject treatment, boolean isDelta, boolean isLocalBypass) {
public static void handleNewTreatment(JSONObject treatment, boolean isDelta) {
Bundle bundle = new Bundle();
bundle.putString("treatment", treatment.toString());
bundle.putBoolean("delta", isDelta);
bundle.putBoolean("islocal", isLocalBypass);
Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT);
intent.putExtras(bundle);
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);

View file

@ -1,43 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient.data;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.utils.ToastUtils;
/**
* Created by mike on 02.07.2016.
*/
public class DbLogger {
private static Logger log = LoggerFactory.getLogger(L.NSCLIENT);
public static void dbAdd(Intent intent, String data) {
List<ResolveInfo> q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(intent, 0);
if (q.size() < 1) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.nsclientnotinstalled));
log.error("DBADD No receivers");
} else if (L.isEnabled(L.NSCLIENT)) {
if (L.isEnabled(L.NSCLIENT))
log.debug("DBADD dbAdd " + q.size() + " receivers " + data);
}
}
public static void dbRemove(Intent intent, String data) {
List<ResolveInfo> q = MainApp.instance().getApplicationContext().getPackageManager().queryBroadcastReceivers(intent, 0);
if (q.size() < 1) {
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.nsclientnotinstalled));
log.error("DBREMOVE No receivers");
} else if (L.isEnabled(L.NSCLIENT)) {
if (L.isEnabled(L.NSCLIENT))
log.debug("DBREMOVE dbRemove " + q.size() + " receivers " + data);
}
}
}

View file

@ -407,7 +407,7 @@ public class NSDeviceStatus {
}
Uploader uploader = uploaders.get(device);
// check if this is new data
if (clock != 0 && (uploader != null && clock > uploader.clock || uploader == null)) {
if (clock != 0 && battery != null && (uploader != null && clock > uploader.clock || uploader == null)) {
if (uploader == null)
uploader = new Uploader();
uploader.battery = battery;

View file

@ -1,60 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.PowerManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.data.AlarmAck;
import info.nightscout.androidaps.plugins.general.nsclient.services.NSClientService;
import info.nightscout.androidaps.utils.SP;
public class AckAlarmReceiver extends BroadcastReceiver {
private static Logger log = LoggerFactory.getLogger(L.NSCLIENT);
@Override
public void onReceive(Context context, Intent intent) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
AckAlarmReceiver.class.getSimpleName());
NSClientPlugin nsClientPlugin = NSClientPlugin.getPlugin();
if (!nsClientPlugin.isEnabled(PluginType.GENERAL)) {
return;
}
if (SP.getBoolean(R.string.key_ns_noupload, false)) {
if (L.isEnabled(L.NSCLIENT))
log.debug("Upload disabled. Message dropped");
return;
}
wakeLock.acquire();
try {
Bundle bundles = intent.getExtras();
if (bundles == null) return;
if (!bundles.containsKey("level")) return;
if (!bundles.containsKey("group")) return;
if (!bundles.containsKey("silenceTime")) return;
AlarmAck ack = new AlarmAck();
ack.level = bundles.getInt("level");
ack.group = bundles.getString("group");
ack.silenceTime = bundles.getLong("silenceTime");
NSClientService nsClientService = nsClientPlugin.nsClientService;
if (nsClientService != null)
nsClientService.sendAlarmAck(ack);
} finally {
wakeLock.release();
}
}
}

View file

@ -1,147 +0,0 @@
package info.nightscout.androidaps.plugins.general.nsclient.receivers;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.PowerManager;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.DbRequest;
import info.nightscout.androidaps.interfaces.PluginType;
import info.nightscout.androidaps.logging.BundleLogger;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.UploadQueue;
import info.nightscout.androidaps.plugins.general.nsclient.broadcasts.BroadcastTreatment;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.SP;
public class DBAccessReceiver extends BroadcastReceiver {
private static Logger log = LoggerFactory.getLogger(L.NSCLIENT);
@Override
public void onReceive(Context context, Intent intent) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
DBAccessReceiver.class.getSimpleName());
wakeLock.acquire();
try {
Bundle bundles = intent.getExtras();
if (bundles == null) return;
if (!bundles.containsKey("action")) return;
if (L.isEnabled(L.NSCLIENT))
log.debug(BundleLogger.log(bundles));
String collection = null;
String _id = null;
JSONObject data = null;
String action = bundles.getString("action");
try {
collection = bundles.getString("collection");
} catch (Exception e) {
log.error("Unhandled exception", e);
return;
}
try {
if (!action.equals("dbAdd"))
_id = bundles.getString("_id");
} catch (Exception e) {
log.error("Unhandled exception", e);
return;
}
try {
if (!action.equals("dbRemove"))
data = new JSONObject(bundles.getString("data"));
} catch (Exception e) {
log.error("Unhandled exception", e);
return;
}
if (data == null && !action.equals("dbRemove") || _id == null && action.equals("dbRemove")) {
log.error("DBACCESS no data inside record");
return;
}
if (action.equals("dbRemove")) {
data = new JSONObject();
}
// mark by id
Long nsclientid = System.currentTimeMillis();
try {
data.put("NSCLIENT_ID", nsclientid);
} catch (JSONException e) {
log.error("Unhandled exception", e);
}
if (!isAllowedCollection(collection)) {
log.error("DBACCESS wrong collection specified");
return;
}
if (action.equals("dbRemove")) {
if (shouldUpload()) {
DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), _id);
UploadQueue.add(dbr);
}
} else if (action.equals("dbUpdate")) {
if (shouldUpload()) {
DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), _id, data);
UploadQueue.add(dbr);
}
} else {
DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), data);
// this is not used as mongo _id but only for searching in UploadQueue database
// if record has to be removed from queue before upload
dbr._id = nsclientid.toString();
if (shouldUpload()) {
UploadQueue.add(dbr);
}
if (collection.equals("treatments")) {
generateTreatmentOfflineBroadcast(dbr);
}
}
} finally {
wakeLock.release();
}
}
public boolean shouldUpload() {
NSClientPlugin nsClientPlugin = NSClientPlugin.getPlugin();
return nsClientPlugin.isEnabled(PluginType.GENERAL) && !SP.getBoolean(R.string.key_ns_noupload, false);
}
public void generateTreatmentOfflineBroadcast(DbRequest request) {
if (request.action.equals("dbAdd")) {
try {
JSONObject data = new JSONObject(request.data);
data.put("mills", DateUtil.fromISODateString(data.getString("created_at")).getTime());
data.put("_id", data.get("NSCLIENT_ID")); // this is only fake id
BroadcastTreatment.handleNewTreatment(data, false, true);
} catch (Exception e) {
log.error("Unhadled exception", e);
}
}
}
private boolean isAllowedCollection(String collection) {
// "treatments" || "entries" || "devicestatus" || "profile" || "food"
if (collection.equals("treatments")) return true;
if (collection.equals("entries")) return true;
if (collection.equals("devicestatus")) return true;
if (collection.equals("profile")) return true;
if (collection.equals("food")) return true;
return false;
}
}

View file

@ -61,6 +61,14 @@ import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.dialogs.CalibrationDialog;
import info.nightscout.androidaps.dialogs.CarbsDialog;
import info.nightscout.androidaps.dialogs.InsulinDialog;
import info.nightscout.androidaps.dialogs.ProfileSwitchDialog;
import info.nightscout.androidaps.dialogs.ProfileViewerDialog;
import info.nightscout.androidaps.dialogs.TempTargetDialog;
import info.nightscout.androidaps.dialogs.TreatmentDialog;
import info.nightscout.androidaps.dialogs.WizardDialog;
import info.nightscout.androidaps.events.EventAcceptOpenLoopChange;
import info.nightscout.androidaps.events.EventCareportalEventChange;
import info.nightscout.androidaps.events.EventExtendedBolusChange;
@ -84,16 +92,9 @@ import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.careportal.CareportalFragment;
import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.general.careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus;
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity;
import info.nightscout.androidaps.plugins.general.overview.dialogs.CalibrationDialog;
import info.nightscout.androidaps.plugins.general.overview.dialogs.NewCarbsDialog;
import info.nightscout.androidaps.plugins.general.overview.dialogs.NewInsulinDialog;
import info.nightscout.androidaps.plugins.general.overview.dialogs.NewTreatmentDialog;
import info.nightscout.androidaps.plugins.general.overview.dialogs.WizardDialog;
import info.nightscout.androidaps.plugins.general.overview.graphData.GraphData;
import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.AutosensData;
@ -105,7 +106,6 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventIobCa
import info.nightscout.androidaps.plugins.source.SourceDexcomPlugin;
import info.nightscout.androidaps.plugins.source.SourceXdripPlugin;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.plugins.treatments.fragments.ProfileViewerDialog;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.BolusWizard;
import info.nightscout.androidaps.utils.DateUtil;
@ -744,11 +744,9 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
updateGUI("suspendmenu");
return true;
} else if (item.getTitle().equals(MainApp.gs(R.string.careportal_profileswitch))) {
NewNSTreatmentDialog newDialog = new NewNSTreatmentDialog();
final OptionsToShow profileswitch = CareportalFragment.PROFILESWITCHDIRECT;
profileswitch.executeProfileSwitch = true;
newDialog.setOptions(profileswitch, R.string.careportal_profileswitch);
newDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
FragmentManager manager = getFragmentManager();
if (manager != null)
new ProfileSwitchDialog().show(manager, "Overview");
} else if (item.getTitle().equals(MainApp.gs(R.string.danar_viewprofile))) {
Bundle args = new Bundle();
args.putLong("time", DateUtil.now());
@ -759,44 +757,39 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (manager != null)
pvd.show(manager, "ProfileViewDialog");
} else if (item.getTitle().equals(MainApp.gs(R.string.eatingsoon))) {
DefaultValueHelper defHelper = new DefaultValueHelper();
double target = Profile.toMgdl(defHelper.determineEatingSoonTT(), ProfileFunctions.getSystemUnits());
double target = Profile.toMgdl(DefaultValueHelper.determineEatingSoonTT(), ProfileFunctions.getSystemUnits());
TempTarget tempTarget = new TempTarget()
.date(System.currentTimeMillis())
.duration(defHelper.determineEatingSoonTTDuration())
.duration(DefaultValueHelper.determineEatingSoonTTDuration())
.reason(MainApp.gs(R.string.eatingsoon))
.source(Source.USER)
.low(target)
.high(target);
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
} else if (item.getTitle().equals(MainApp.gs(R.string.activity))) {
DefaultValueHelper defHelper = new DefaultValueHelper();
double target = Profile.toMgdl(defHelper.determineActivityTT(), ProfileFunctions.getSystemUnits());
double target = Profile.toMgdl(DefaultValueHelper.determineActivityTT(), ProfileFunctions.getSystemUnits());
TempTarget tempTarget = new TempTarget()
.date(now())
.duration(defHelper.determineActivityTTDuration())
.duration(DefaultValueHelper.determineActivityTTDuration())
.reason(MainApp.gs(R.string.activity))
.source(Source.USER)
.low(target)
.high(target);
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
} else if (item.getTitle().equals(MainApp.gs(R.string.hypo))) {
DefaultValueHelper defHelper = new DefaultValueHelper();
double target = Profile.toMgdl(defHelper.determineHypoTT(), ProfileFunctions.getSystemUnits());
double target = Profile.toMgdl(DefaultValueHelper.determineHypoTT(), ProfileFunctions.getSystemUnits());
TempTarget tempTarget = new TempTarget()
.date(now())
.duration(defHelper.determineHypoTTDuration())
.duration(DefaultValueHelper.determineHypoTTDuration())
.reason(MainApp.gs(R.string.hypo))
.source(Source.USER)
.low(target)
.high(target);
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
} else if (item.getTitle().equals(MainApp.gs(R.string.custom))) {
NewNSTreatmentDialog newTTDialog = new NewNSTreatmentDialog();
final OptionsToShow temptarget = CareportalFragment.TEMPTARGET;
temptarget.executeTempTarget = true;
newTTDialog.setOptions(temptarget, R.string.careportal_temporarytarget);
newTTDialog.show(getFragmentManager(), "NewNSTreatmentDialog");
FragmentManager manager = getFragmentManager();
if (manager != null)
new TempTargetDialog().show(manager, "Overview");
} else if (item.getTitle().equals(MainApp.gs(R.string.cancel))) {
TempTarget tempTarget = new TempTarget()
.source(Source.USER)
@ -818,7 +811,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
FragmentManager manager = getFragmentManager();
// try to fix https://fabric.io/nightscout3/android/apps/info.nightscout.androidaps/issues/5aca7a1536c7b23527eb4be7?time=last-seven-days
// https://stackoverflow.com/questions/14860239/checking-if-state-is-saved-before-committing-a-fragmenttransaction
if (manager.isStateSaved())
if (manager == null || manager.isStateSaved())
return;
switch (v.getId()) {
case R.id.overview_accepttempbutton:
@ -863,14 +856,13 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
break;
case R.id.overview_treatmentbutton:
NewTreatmentDialog treatmentDialogFragment = new NewTreatmentDialog();
treatmentDialogFragment.show(manager, "TreatmentDialog");
new TreatmentDialog().show(manager, "Overview");
break;
case R.id.overview_insulinbutton:
new NewInsulinDialog().show(manager, "InsulinDialog");
new InsulinDialog().show(manager, "Overview");
break;
case R.id.overview_carbsbutton:
new NewCarbsDialog().show(manager, "CarbsDialog");
new CarbsDialog().show(manager, "Overview");
break;
case R.id.overview_pumpstatus:
if (ConfigBuilderPlugin.getPlugin().getActivePump().isSuspended() || !ConfigBuilderPlugin.getPlugin().getActivePump().isInitialized())
@ -891,10 +883,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
getContext().startActivity(intent);
return true;
} catch (ActivityNotFoundException e) {
new AlertDialog.Builder(getContext())
.setMessage(R.string.error_starting_cgm)
.setPositiveButton("OK", null)
.show();
OKDialog.show(getContext(), "", MainApp.gs(R.string.error_starting_cgm));
return false;
}
}
@ -920,16 +909,11 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
LoopPlugin.getPlugin().invoke("Accept temp button", false);
final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun;
if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.isChangeRequested()) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(MainApp.gs(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed);
builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
OKDialog.showConfirmation(context, MainApp.gs(R.string.pump_tempbasal_label), finalLastRun.constraintsProcessed.toSpanned(), () -> {
hideTempRecommendation();
clearNotification();
LoopPlugin.getPlugin().acceptChangeRequest();
});
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
}
}
}
@ -949,7 +933,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(quickWizardEntry.carbs())).value();
if (Math.abs(wizard.getInsulinAfterConstraints() - wizard.getCalculatedTotalInsulin()) >= pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(wizard.getInsulinAfterConstraints()) || !carbsAfterConstraints.equals(quickWizardEntry.carbs())) {
OKDialog.show(getContext(), MainApp.gs(R.string.treatmentdeliveryerror), MainApp.gs(R.string.constraints_violation) + "\n" + MainApp.gs(R.string.changeyourinput), null);
OKDialog.show(getContext(), MainApp.gs(R.string.treatmentdeliveryerror), MainApp.gs(R.string.constraints_violation) + "\n" + MainApp.gs(R.string.changeyourinput));
return;
}
@ -1178,7 +1162,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
if (activeTemp != null) {
fullText += MainApp.gs(R.string.pump_tempbasal_label) + ": " + activeTemp.toStringFull();
}
OKDialog.show(getActivity(), MainApp.gs(R.string.basal), fullText, null);
OKDialog.show(getActivity(), MainApp.gs(R.string.basal), fullText);
});
} else {
@ -1214,7 +1198,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
}
extendedBolusView.setText(extendedBolusText);
if (Config.NSCLIENT) {
extendedBolusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.extendedbolus), extendedBolus.toString(), null));
extendedBolusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.extended_bolus), extendedBolus.toString()));
}
if (extendedBolusText.equals(""))
extendedBolusView.setVisibility(Config.NSCLIENT ? View.INVISIBLE : View.GONE);
@ -1308,7 +1292,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
String iobtext1 = DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U\n"
+ MainApp.gs(R.string.bolus) + ": " + DecimalFormatter.to2Decimal(bolusIob.iob) + "U\n"
+ MainApp.gs(R.string.basal) + ": " + DecimalFormatter.to2Decimal(basalIob.basaliob) + "U\n";
OKDialog.show(getActivity(), MainApp.gs(R.string.iob), iobtext1, null);
OKDialog.show(getActivity(), MainApp.gs(R.string.iob), iobtext1);
});
} else if (MainApp.sResources.getBoolean(R.bool.isTablet)) {
String iobtext = DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob) + "U ("
@ -1360,19 +1344,19 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
// pump status from ns
if (pumpDeviceStatusView != null) {
pumpDeviceStatusView.setText(NSDeviceStatus.getInstance().getPumpStatus());
pumpDeviceStatusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.pump), NSDeviceStatus.getInstance().getExtendedPumpStatus(), null));
pumpDeviceStatusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.pump), NSDeviceStatus.getInstance().getExtendedPumpStatus()));
}
// OpenAPS status from ns
if (openapsDeviceStatusView != null) {
openapsDeviceStatusView.setText(NSDeviceStatus.getInstance().getOpenApsStatus());
openapsDeviceStatusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.openaps), NSDeviceStatus.getInstance().getExtendedOpenApsStatus(), null));
openapsDeviceStatusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.openaps), NSDeviceStatus.getInstance().getExtendedOpenApsStatus()));
}
// Uploader status from ns
if (uploaderDeviceStatusView != null) {
uploaderDeviceStatusView.setText(NSDeviceStatus.getInstance().getUploaderStatusSpanned());
uploaderDeviceStatusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.uploader), NSDeviceStatus.getInstance().getExtendedUploaderStatus(), null));
uploaderDeviceStatusView.setOnClickListener(v -> OKDialog.show(getActivity(), MainApp.gs(R.string.uploader), NSDeviceStatus.getInstance().getExtendedUploaderStatus()));
}
// Sensitivity

View file

@ -1,198 +0,0 @@
package info.nightscout.androidaps.plugins.general.overview.dialogs;
import android.app.Activity;
import android.os.Bundle;
import android.os.SystemClock;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.events.EventPumpStatusChanged;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning;
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.utils.FabricPrivacy;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
public class BolusProgressDialog extends DialogFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(L.UI);
private CompositeDisposable disposable = new CompositeDisposable();
Button stopButton;
TextView statusView;
TextView stopPressedView;
ProgressBar progressBar;
BolusProgressHelperActivity helperActivity;
static double amount;
public static boolean bolusEnded = false;
public static boolean running = true;
public static boolean stopPressed = false;
private String state;
private final static String DEFAULT_STATE = MainApp.gs(R.string.waitingforpump);
public BolusProgressDialog() {
super();
}
public void setInsulin(double amount) {
BolusProgressDialog.amount = amount;
bolusEnded = false;
}
public void setHelperActivity(BolusProgressHelperActivity activity) {
this.helperActivity = activity;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getDialog().setTitle(String.format(MainApp.gs(R.string.overview_bolusprogress_goingtodeliver), amount));
View view = inflater.inflate(R.layout.overview_bolusprogress_dialog, container, false);
stopButton = view.findViewById(R.id.overview_bolusprogress_stop);
statusView = view.findViewById(R.id.overview_bolusprogress_status);
stopPressedView = view.findViewById(R.id.overview_bolusprogress_stoppressed);
progressBar = view.findViewById(R.id.overview_bolusprogress_progressbar);
stopButton.setOnClickListener(this);
progressBar.setMax(100);
state = savedInstanceState != null ? savedInstanceState.getString("state", DEFAULT_STATE) : DEFAULT_STATE;
statusView.setText(state);
setCancelable(false);
stopPressed = false;
return view;
}
@Override
public void onResume() {
super.onResume();
if (L.isEnabled(L.UI))
log.debug("onResume");
if (!ConfigBuilderPlugin.getPlugin().getCommandQueue().bolusInQueue()) {
bolusEnded = true;
}
if (bolusEnded) {
dismiss();
} else {
if (getDialog() != null)
getDialog().getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
running = true;
if (L.isEnabled(L.UI))
log.debug("onResume running");
}
disposable.add(RxBus.INSTANCE
.toObservable(EventPumpStatusChanged.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(event -> statusView.setText(event.getStatus()), FabricPrivacy::logException)
);
disposable.add(RxBus.INSTANCE
.toObservable(EventDismissBolusProgressIfRunning.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(event -> {
if (L.isEnabled(L.UI)) log.debug("EventDismissBolusProgressIfRunning");
if (BolusProgressDialog.running) dismiss();
}, FabricPrivacy::logException)
);
disposable.add(RxBus.INSTANCE
.toObservable(EventOverviewBolusProgress.class)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(event -> {
if (L.isEnabled(L.UI))
log.debug("Status: " + event.getStatus() + " Percent: " + event.getPercent());
statusView.setText(event.getStatus());
progressBar.setProgress(event.getPercent());
if (event.getPercent() == 100) {
stopButton.setVisibility(View.INVISIBLE);
scheduleDismiss();
}
state = event.getStatus();
}, FabricPrivacy::logException)
);
}
@Override
public void dismiss() {
if (L.isEnabled(L.UI))
log.debug("dismiss");
try {
super.dismiss();
} catch (IllegalStateException e) {
// dialog not running yet. onResume will try again. Set bolusEnded to make extra
// sure onResume will catch this
bolusEnded = true;
log.error("Unhandled exception", e);
}
if (helperActivity != null) {
helperActivity.finish();
}
}
@Override
public void onPause() {
if (L.isEnabled(L.UI))
log.debug("onPause");
running = false;
super.onPause();
disposable.clear();
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
outState.putString("state", state);
log.debug("storing state: " + state);
super.onSaveInstanceState(outState);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.overview_bolusprogress_stop:
if (L.isEnabled(L.UI))
log.debug("Stop bolus delivery button pressed");
stopPressed = true;
stopPressedView.setVisibility(View.VISIBLE);
stopButton.setVisibility(View.INVISIBLE);
ConfigBuilderPlugin.getPlugin().getCommandQueue().cancelAllBoluses();
break;
}
}
private void scheduleDismiss() {
if (L.isEnabled(L.UI))
log.debug("scheduleDismiss");
Thread t = new Thread(() -> {
SystemClock.sleep(5000);
BolusProgressDialog.bolusEnded = true;
Activity activity = getActivity();
if (activity != null) {
activity.runOnUiThread(() -> {
try {
if (running) {
if (L.isEnabled(L.UI))
log.debug("executing");
dismiss();
}
} catch (Exception e) {
log.error("Unhandled exception", e);
}
});
}
});
t.start();
}
}

View file

@ -1,20 +0,0 @@
package info.nightscout.androidaps.plugins.general.overview.dialogs;
import android.os.Bundle;
import info.nightscout.androidaps.activities.NoSplashAppCompatActivity;
public class BolusProgressHelperActivity extends NoSplashAppCompatActivity {
public BolusProgressHelperActivity() {
super();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
BolusProgressDialog bolusProgressDialog = new BolusProgressDialog();
bolusProgressDialog.setHelperActivity(this);
bolusProgressDialog.setInsulin(getIntent().getDoubleExtra("insulin", 0d));
bolusProgressDialog.show(getSupportFragmentManager(), "BolusProgress");
}
}

View file

@ -1,94 +0,0 @@
package info.nightscout.androidaps.plugins.general.overview.dialogs;
import android.content.Context;
import android.os.Bundle;
import androidx.fragment.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.utils.NumberPicker;
import info.nightscout.androidaps.utils.SafeParse;
import info.nightscout.androidaps.utils.XdripCalibrations;
public class CalibrationDialog extends DialogFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(CalibrationDialog.class);
NumberPicker bgNumber;
TextView unitsView;
Context context;
public CalibrationDialog() {
// Required empty public constructor
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
this.context = context;
}
@Override
public void onDetach() {
super.onDetach();
this.context = null;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.overview_calibration_dialog, container, false);
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this);
String units = ProfileFunctions.getSystemUnits();
Double bg = Profile.fromMgdlToUnits(GlucoseStatus.getGlucoseStatusData() != null ? GlucoseStatus.getGlucoseStatusData().glucose : 0d, units);
bgNumber = (NumberPicker) view.findViewById(R.id.overview_calibration_bg);
if (units.equals(Constants.MMOL))
bgNumber.setParams(bg, 0d, 30d, 0.1d, new DecimalFormat("0.0"), false, view.findViewById(R.id.ok));
else
bgNumber.setParams(bg, 0d, 500d, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok));
unitsView = (TextView) view.findViewById(R.id.overview_calibration_units);
unitsView.setText(units);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.ok:
final Double bg = SafeParse.stringToDouble(bgNumber.getText());
XdripCalibrations.confirmAndSendCalibration(bg, context);
dismiss();
break;
case R.id.cancel:
dismiss();
break;
}
}
}

View file

@ -1,443 +0,0 @@
package info.nightscout.androidaps.plugins.general.overview.dialogs;
import android.os.Bundle;
import androidx.fragment.app.DialogFragment;
import androidx.appcompat.app.AlertDialog;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import com.google.common.base.Joiner;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import java.util.LinkedList;
import java.util.List;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.plugins.treatments.CarbsGenerator;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.DefaultValueHelper;
import info.nightscout.androidaps.utils.NumberPicker;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.ToastUtils;
import static info.nightscout.androidaps.utils.DateUtil.now;
public class NewCarbsDialog extends DialogFragment implements OnClickListener, CompoundButton.OnCheckedChangeListener {
private static Logger log = LoggerFactory.getLogger(NewCarbsDialog.class);
private static final int FAV1_DEFAULT = 5;
private static final int FAV2_DEFAULT = 10;
private static final int FAV3_DEFAULT = 20;
private RadioButton startActivityTTCheckbox;
private RadioButton startEatingSoonTTCheckbox;
private RadioButton startHypoTTCheckbox;
private boolean togglingTT;
private NumberPicker editTime;
private NumberPicker editDuration;
private NumberPicker editCarbs;
private Integer maxCarbs;
private EditText notesEdit;
//one shot guards
private boolean accepted;
private boolean okClicked;
public NewCarbsDialog() {
}
final private TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
validateInputs();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
};
private void validateInputs() {
int time = editTime.getValue().intValue();
if (time > 12 * 60 || time < -12 * 60) {
editTime.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.constraintapllied));
}
Double duration = editDuration.getValue();
if (duration > 10) {
editDuration.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.constraintapllied));
}
int carbs = editCarbs.getValue().intValue();
if (carbs > maxCarbs) {
editCarbs.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.carbsconstraintapplied));
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.overview_newcarbs_dialog, container, false);
view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this);
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
startActivityTTCheckbox = view.findViewById(R.id.newcarbs_activity_tt);
startActivityTTCheckbox.setOnCheckedChangeListener(this);
startEatingSoonTTCheckbox = view.findViewById(R.id.newcarbs_eating_soon_tt);
startEatingSoonTTCheckbox.setOnCheckedChangeListener(this);
startHypoTTCheckbox = view.findViewById(R.id.newcarbs_hypo_tt);
editTime = view.findViewById(R.id.newcarbs_time);
editTime.setParams(0d, -12 * 60d, 12 * 60d, 5d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), textWatcher);
editDuration = view.findViewById(R.id.new_carbs_duration);
editDuration.setParams(0d, 0d, 10d, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), textWatcher);
maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value();
editCarbs = view.findViewById(R.id.newcarb_carbsamount);
editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), textWatcher);
Button fav1Button = view.findViewById(R.id.newcarbs_plus1);
fav1Button.setOnClickListener(this);
fav1Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT)));
Button fav2Button = view.findViewById(R.id.newcarbs_plus2);
fav2Button.setOnClickListener(this);
fav2Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT)));
Button fav3Button = view.findViewById(R.id.newcarbs_plus3);
fav3Button.setOnClickListener(this);
fav3Button.setText(toSignedString(SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT)));
LinearLayout notesLayout = view.findViewById(R.id.newcarbs_notes_layout);
notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE);
notesEdit = view.findViewById(R.id.newcarbs_notes);
BgReading bgReading = DatabaseHelper.actualBg();
if (bgReading != null && bgReading.value < 72) {
startHypoTTCheckbox.setChecked(true);
// see #onCheckedChanged why listeners are registered like this
startHypoTTCheckbox.setOnClickListener(this);
} else {
startHypoTTCheckbox.setOnCheckedChangeListener(this);
}
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
//recovering state if there is something
if (savedInstanceState != null) {
editCarbs.setValue(savedInstanceState.getDouble("editCarbs"));
editTime.setValue(savedInstanceState.getDouble("editTime"));
editDuration.setValue(savedInstanceState.getDouble("editDuration"));
}
return view;
}
private String toSignedString(int value) {
return value > 0 ? "+" + value : String.valueOf(value);
}
@Override
public void onSaveInstanceState(Bundle carbsDialogState) {
carbsDialogState.putBoolean("startActivityTTCheckbox",startActivityTTCheckbox.isChecked());
carbsDialogState.putBoolean("startEatingSoonTTCheckbox", startEatingSoonTTCheckbox.isChecked());
carbsDialogState.putBoolean("startHypoTTCheckbox", startHypoTTCheckbox.isChecked());
carbsDialogState.putDouble("editTime", editTime.getValue());
carbsDialogState.putDouble("editDuration", editDuration.getValue());
carbsDialogState.putDouble("editCarbs", editCarbs.getValue());
super.onSaveInstanceState(carbsDialogState);
}
@Override
public synchronized void onClick(View view) {
switch (view.getId()) {
case R.id.ok:
submit();
break;
case R.id.cancel:
dismiss();
break;
case R.id.newcarbs_plus1:
editCarbs.setValue(Math.max(0, editCarbs.getValue()
+ SP.getInt(R.string.key_carbs_button_increment_1, FAV1_DEFAULT)));
validateInputs();
break;
case R.id.newcarbs_plus2:
editCarbs.setValue(Math.max(0, editCarbs.getValue()
+ SP.getInt(R.string.key_carbs_button_increment_2, FAV2_DEFAULT)));
validateInputs();
break;
case R.id.newcarbs_plus3:
editCarbs.setValue(Math.max(0, editCarbs.getValue()
+ SP.getInt(R.string.key_carbs_button_increment_3, FAV3_DEFAULT)));
validateInputs();
break;
case R.id.newcarbs_activity_tt:
if (togglingTT) {
togglingTT = false;
break;
}
startActivityTTCheckbox.setOnClickListener(null);
startActivityTTCheckbox.setOnCheckedChangeListener(null);
startActivityTTCheckbox.setChecked(false);
startActivityTTCheckbox.setOnCheckedChangeListener(this);
break;
case R.id.newcarbs_eating_soon_tt:
if (togglingTT) {
togglingTT = false;
break;
}
startEatingSoonTTCheckbox.setOnClickListener(null);
startEatingSoonTTCheckbox.setOnCheckedChangeListener(null);
startEatingSoonTTCheckbox.setChecked(false);
startEatingSoonTTCheckbox.setOnCheckedChangeListener(this);
break;
case R.id.newcarbs_hypo_tt:
if (togglingTT) {
togglingTT = false;
break;
}
startHypoTTCheckbox.setOnClickListener(null);
startHypoTTCheckbox.setOnCheckedChangeListener(null);
startHypoTTCheckbox.setChecked(false);
startHypoTTCheckbox.setOnCheckedChangeListener(this);
break;
}
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// Logic to disable a selected radio when pressed: when a checked radio
// is pressed, no CheckChanged event is triggered, so register a Click event
// when checking a radio. Since Click events come after CheckChanged events,
// the Click event is triggered immediately after this. Thus, set togglingTT
// var to true, so that the first Click event fired after this is ignored.
// Radios remove themselves from Click events once unchecked.
// Since radios are not in a group, their state is manually updated here.
switch (buttonView.getId()) {
case R.id.newcarbs_activity_tt:
togglingTT = true;
startActivityTTCheckbox.setOnClickListener(this);
startEatingSoonTTCheckbox.setOnCheckedChangeListener(null);
startEatingSoonTTCheckbox.setChecked(false);
startEatingSoonTTCheckbox.setOnCheckedChangeListener(this);
startHypoTTCheckbox.setOnCheckedChangeListener(null);
startHypoTTCheckbox.setChecked(false);
startHypoTTCheckbox.setOnCheckedChangeListener(this);
break;
case R.id.newcarbs_eating_soon_tt:
togglingTT = true;
startEatingSoonTTCheckbox.setOnClickListener(this);
startActivityTTCheckbox.setOnCheckedChangeListener(null);
startActivityTTCheckbox.setChecked(false);
startActivityTTCheckbox.setOnCheckedChangeListener(this);
startHypoTTCheckbox.setOnCheckedChangeListener(null);
startHypoTTCheckbox.setChecked(false);
startHypoTTCheckbox.setOnCheckedChangeListener(this);
break;
case R.id.newcarbs_hypo_tt:
togglingTT = true;
startHypoTTCheckbox.setOnClickListener(this);
startActivityTTCheckbox.setOnCheckedChangeListener(null);
startActivityTTCheckbox.setChecked(false);
startActivityTTCheckbox.setOnCheckedChangeListener(this);
startEatingSoonTTCheckbox.setOnCheckedChangeListener(null);
startEatingSoonTTCheckbox.setChecked(false);
startEatingSoonTTCheckbox.setOnCheckedChangeListener(this);
break;
}
}
private void submit() {
if (okClicked) {
log.debug("guarding: ok already clicked");
dismiss();
return;
}
okClicked = true;
try {
final Profile currentProfile = ProfileFunctions.getInstance().getProfile();
if (currentProfile == null) {
return;
}
int carbs = editCarbs.getValue().intValue();
Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(carbs)).value();
final String units = ProfileFunctions.getSystemUnits();
DefaultValueHelper helper = new DefaultValueHelper();
int activityTTDuration = helper.determineActivityTTDuration();
double activityTT = helper.determineActivityTT();
int eatingSoonTTDuration = helper.determineEatingSoonTTDuration();
double eatingSoonTT = helper.determineEatingSoonTT();
int hypoTTDuration = helper.determineHypoTTDuration();
double hypoTT = helper.determineHypoTT();
List<String> actions = new LinkedList<>();
if (startActivityTTCheckbox.isChecked()) {
String unitLabel = "mg/dl";
if (units.equals(Constants.MMOL)) {
unitLabel = "mmol/l";
}
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(activityTT) + " " + unitLabel + " (" + activityTTDuration + " min)</font>");
}
if (startEatingSoonTTCheckbox.isChecked()) {
if (units.equals(Constants.MMOL)) {
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(eatingSoonTT) + " mmol/l (" + eatingSoonTTDuration + " min)</font>");
} else {
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to0Decimal(eatingSoonTT) + " mg/dl (" + eatingSoonTTDuration + " min)</font>");
}
}
if (startHypoTTCheckbox.isChecked()) {
if (units.equals(Constants.MMOL)) {
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(hypoTT) + " mmol/l (" + hypoTTDuration + " min)</font>");
} else {
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to0Decimal(hypoTT) + " mg/dl (" + hypoTTDuration + " min)</font>");
}
}
int timeOffset = editTime.getValue().intValue();
final long time = now() + timeOffset * 1000 * 60;
if (timeOffset != 0) {
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time));
}
int duration = editDuration.getValue().intValue();
if (duration > 0) {
actions.add(MainApp.gs(R.string.duration) + ": " + duration + MainApp.gs(R.string.shorthour));
}
if (carbs > 0) {
actions.add(MainApp.gs(R.string.carbs) + ": " + "<font color='" + MainApp.gc(R.color.carbs) + "'>" + carbsAfterConstraints + "g" + "</font>");
}
if (!carbsAfterConstraints.equals(carbs)) {
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.carbsconstraintapplied) + "</font>");
}
final String notes = notesEdit.getText().toString();
if (!notes.isEmpty()) {
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes);
}
final double finalActivityTT = activityTT;
final int finalActivityTTDuration = activityTTDuration;
final double finalEatigSoonTT = eatingSoonTT;
final int finalEatingSoonTTDuration = eatingSoonTTDuration;
final double finalHypoTT = hypoTT;
final int finalHypoTTDuration = hypoTTDuration;
final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle(MainApp.gs(R.string.confirmation));
if (carbsAfterConstraints > 0 || startActivityTTCheckbox.isChecked()
|| startEatingSoonTTCheckbox.isChecked() || startHypoTTCheckbox.isChecked()) {
builder.setMessage(Html.fromHtml(Joiner.on("<br/>").join(actions)));
builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
synchronized (builder) {
if (accepted) {
log.debug("guarding: already accepted");
return;
}
accepted = true;
if (startActivityTTCheckbox.isChecked()) {
TempTarget tempTarget = new TempTarget()
.date(System.currentTimeMillis())
.duration(finalActivityTTDuration)
.reason(MainApp.gs(R.string.activity))
.source(Source.USER)
.low(Profile.toMgdl(finalActivityTT, ProfileFunctions.getSystemUnits()))
.high(Profile.toMgdl(finalActivityTT, ProfileFunctions.getSystemUnits()));
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
} else if (startEatingSoonTTCheckbox.isChecked()) {
TempTarget tempTarget = new TempTarget()
.date(System.currentTimeMillis())
.duration(finalEatingSoonTTDuration)
.reason(MainApp.gs(R.string.eatingsoon))
.source(Source.USER)
.low(Profile.toMgdl(finalEatigSoonTT, ProfileFunctions.getSystemUnits()))
.high(Profile.toMgdl(finalEatigSoonTT, ProfileFunctions.getSystemUnits()));
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
} else if (startHypoTTCheckbox.isChecked()) {
TempTarget tempTarget = new TempTarget()
.date(System.currentTimeMillis())
.duration(finalHypoTTDuration)
.reason(MainApp.gs(R.string.hypo))
.source(Source.USER)
.low(Profile.toMgdl(finalHypoTT, ProfileFunctions.getSystemUnits()))
.high(Profile.toMgdl(finalHypoTT, ProfileFunctions.getSystemUnits()));
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
}
if (carbsAfterConstraints > 0) {
if (duration == 0) {
CarbsGenerator.createCarb(carbsAfterConstraints, time, CareportalEvent.CARBCORRECTION, notes);
} else {
CarbsGenerator.generateCarbs(carbsAfterConstraints, time, duration, notes);
NSUpload.uploadEvent(CareportalEvent.NOTE, now() - 2000, MainApp.gs(R.string.generated_ecarbs_note, carbsAfterConstraints, duration, timeOffset));
}
}
}
});
} else {
builder.setMessage(MainApp.gs(R.string.no_action_selected));
}
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
dismiss();
} catch (Exception e) {
log.error("Unhandled exception", e);
}
}
}

View file

@ -1,317 +0,0 @@
package info.nightscout.androidaps.plugins.general.overview.dialogs;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import androidx.fragment.app.DialogFragment;
import androidx.appcompat.app.AlertDialog;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import com.google.common.base.Joiner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import java.util.LinkedList;
import java.util.List;
import info.nightscout.androidaps.Constants;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TempTarget;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.NumberPicker;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.SafeParse;
import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.utils.ToastUtils;
import static info.nightscout.androidaps.utils.DateUtil.now;
public class NewInsulinDialog extends DialogFragment implements OnClickListener {
private static Logger log = LoggerFactory.getLogger(NewInsulinDialog.class);
private static final double PLUS1_DEFAULT = 0.5d;
private static final double PLUS2_DEFAULT = 1d;
private static final double PLUS3_DEFAULT = 2d;
private CheckBox startEatingSoonTTCheckbox;
private CheckBox recordOnlyCheckbox;
private LinearLayout editLayout;
private NumberPicker editTime;
private NumberPicker editInsulin;
private Double maxInsulin;
private EditText notesEdit;
//one shot guards
private boolean accepted;
private boolean okClicked;
public NewInsulinDialog() {
}
final private TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
validateInputs();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
};
private void validateInputs() {
int time = editTime.getValue().intValue();
if (Math.abs(time) > 12 * 60) {
editTime.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.constraintapllied));
}
Double insulin = editInsulin.getValue();
if (insulin > maxInsulin) {
editInsulin.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.bolusconstraintapplied));
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.overview_newinsulin_dialog, container, false);
view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this);
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
startEatingSoonTTCheckbox = view.findViewById(R.id.newinsulin_start_eating_soon_tt);
recordOnlyCheckbox = view.findViewById(R.id.newinsulin_record_only);
recordOnlyCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> editLayout.setVisibility(isChecked ? View.VISIBLE : View.GONE));
editLayout = view.findViewById(R.id.newinsulin_time_layout);
editLayout.setVisibility(View.GONE);
editTime = view.findViewById(R.id.newinsulin_time);
editTime.setParams(0d, -12 * 60d, 12 * 60d, 5d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), textWatcher);
maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
editInsulin = view.findViewById(R.id.newinsulin_amount);
editInsulin.setParams(0d, 0d, maxInsulin, ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, view.findViewById(R.id.ok), textWatcher);
Button plus1Button = view.findViewById(R.id.newinsulin_plus05);
plus1Button.setOnClickListener(this);
plus1Button.setText(toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT)));
Button plus2Button = view.findViewById(R.id.newinsulin_plus10);
plus2Button.setOnClickListener(this);
plus2Button.setText(toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT)));
Button plus3Button = view.findViewById(R.id.newinsulin_plus20);
plus3Button.setOnClickListener(this);
plus3Button.setText(toSignedString(SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT)));
LinearLayout notesLayout = view.findViewById(R.id.newinsulin_notes_layout);
notesLayout.setVisibility(SP.getBoolean(R.string.key_show_notes_entry_dialogs, false) ? View.VISIBLE : View.GONE);
notesEdit = view.findViewById(R.id.newinsulin_notes);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
if (savedInstanceState != null) {
// log.debug("savedInstanceState in onCreate is:" + savedInstanceState.toString());
editInsulin.setValue(savedInstanceState.getDouble("editInsulin"));
editTime.setValue(savedInstanceState.getDouble("editTime"));
}
return view;
}
private String toSignedString(double value) {
String formatted = DecimalFormatter.toPumpSupportedBolus(value);
return value > 0 ? "+" + formatted : formatted;
}
@Override
public void onSaveInstanceState(Bundle insulinDialogState) {
insulinDialogState.putBoolean("startEatingSoonTTCheckbox", startEatingSoonTTCheckbox.isChecked());
insulinDialogState.putBoolean("recordOnlyCheckbox", recordOnlyCheckbox.isChecked());
insulinDialogState.putDouble("editTime", editTime.getValue());
insulinDialogState.putDouble("editInsulin", editInsulin.getValue());
insulinDialogState.putString("notesEdit", notesEdit.getText().toString());
log.debug("Instance state saved:" + insulinDialogState.toString());
super.onSaveInstanceState(insulinDialogState);
}
@Override
public synchronized void onClick(View view) {
switch (view.getId()) {
case R.id.ok:
submit();
break;
case R.id.cancel:
dismiss();
break;
case R.id.newinsulin_plus05:
editInsulin.setValue(Math.max(0, editInsulin.getValue()
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_1), PLUS1_DEFAULT)));
validateInputs();
break;
case R.id.newinsulin_plus10:
editInsulin.setValue(Math.max(0, editInsulin.getValue()
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_2), PLUS2_DEFAULT)));
validateInputs();
break;
case R.id.newinsulin_plus20:
editInsulin.setValue(Math.max(0, editInsulin.getValue()
+ SP.getDouble(MainApp.gs(R.string.key_insulin_button_increment_3), PLUS3_DEFAULT)));
validateInputs();
break;
}
}
private void submit() {
if (okClicked) {
log.debug("guarding: ok already clicked");
dismiss();
return;
}
okClicked = true;
try {
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
if (pump == null)
return;
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value();
List<String> actions = new LinkedList<>();
if (insulin > 0) {
actions.add(MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.bolus) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + "</font>");
if (recordOnlyCheckbox.isChecked()) {
actions.add("<font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.bolusrecordedonly) + "</font>");
}
}
if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(insulinAfterConstraints))
actions.add(MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints));
int eatingSoonTTDuration = SP.getInt(R.string.key_eatingsoon_duration, Constants.defaultEatingSoonTTDuration);
eatingSoonTTDuration = eatingSoonTTDuration > 0 ? eatingSoonTTDuration : Constants.defaultEatingSoonTTDuration;
double eatingSoonTT = SP.getDouble(R.string.key_eatingsoon_target, ProfileFunctions.getSystemUnits().equals(Constants.MMOL) ? Constants.defaultEatingSoonTTmmol : Constants.defaultEatingSoonTTmgdl);
eatingSoonTT = eatingSoonTT > 0 ? eatingSoonTT : ProfileFunctions.getSystemUnits().equals(Constants.MMOL) ? Constants.defaultEatingSoonTTmmol : Constants.defaultEatingSoonTTmgdl;
if (startEatingSoonTTCheckbox.isChecked()) {
if (ProfileFunctions.getSystemUnits().equals(Constants.MMOL)) {
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to1Decimal(eatingSoonTT) + " mmol/l (" + eatingSoonTTDuration + " min)</font>");
} else
actions.add(MainApp.gs(R.string.temptargetshort) + ": " + "<font color='" + MainApp.gc(R.color.tempTargetConfirmation) + "'>" + DecimalFormatter.to0Decimal(eatingSoonTT) + " mg/dl (" + eatingSoonTTDuration + " min)</font>");
}
int timeOffset = editTime.getValue().intValue();
final long time = now() + T.mins(timeOffset).msecs();
if (timeOffset != 0) {
actions.add(MainApp.gs(R.string.time) + ": " + DateUtil.dateAndTimeString(time));
}
final String notes = notesEdit.getText().toString();
if (!notes.isEmpty()) {
actions.add(MainApp.gs(R.string.careportal_newnstreatment_notes_label) + ": " + notes);
}
final double finalInsulinAfterConstraints = insulinAfterConstraints;
final double finalEatigSoonTT = eatingSoonTT;
final int finalEatingSoonTTDuration = eatingSoonTTDuration;
final Context context = getContext();
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation));
if (finalInsulinAfterConstraints > 0 || startEatingSoonTTCheckbox.isChecked()) {
builder.setMessage(Html.fromHtml(Joiner.on("<br/>").join(actions)));
builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> {
synchronized (builder) {
if (accepted) {
log.debug("guarding: already accepted");
return;
}
accepted = true;
if (startEatingSoonTTCheckbox.isChecked()) {
TempTarget tempTarget = new TempTarget()
.date(System.currentTimeMillis())
.duration(finalEatingSoonTTDuration)
.reason(MainApp.gs(R.string.eatingsoon))
.source(Source.USER)
.low(Profile.toMgdl(finalEatigSoonTT, ProfileFunctions.getSystemUnits()))
.high(Profile.toMgdl(finalEatigSoonTT, ProfileFunctions.getSystemUnits()));
TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget);
}
if (finalInsulinAfterConstraints > 0) {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS;
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER;
detailedBolusInfo.notes = notes;
if (recordOnlyCheckbox.isChecked()) {
detailedBolusInfo.date = time;
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
} else {
detailedBolusInfo.date = now();
ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override
public void run() {
if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
});
}
}
}
});
} else {
builder.setMessage(MainApp.gs(R.string.no_action_selected));
}
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
dismiss();
} catch (Exception e) {
log.error("Unhandled exception", e);
}
}
}

View file

@ -1,213 +0,0 @@
package info.nightscout.androidaps.plugins.general.overview.dialogs;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import androidx.fragment.app.DialogFragment;
import androidx.appcompat.app.AlertDialog;
import android.text.Editable;
import android.text.Html;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.CheckBox;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import java.util.Objects;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.DetailedBolusInfo;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.interfaces.Constraint;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
import info.nightscout.androidaps.queue.Callback;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.NumberPicker;
import info.nightscout.androidaps.utils.SafeParse;
import info.nightscout.androidaps.utils.ToastUtils;
public class NewTreatmentDialog extends DialogFragment implements OnClickListener {
private static Logger log = LoggerFactory.getLogger(NewTreatmentDialog.class);
private NumberPicker editCarbs;
private NumberPicker editInsulin;
private Integer maxCarbs;
private Double maxInsulin;
//one shot guards
private boolean accepted;
private boolean okClicked;
private CheckBox recordOnlyCheckbox;
public NewTreatmentDialog() {
}
final private TextWatcher textWatcher = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
validateInputs();
}
};
private void validateInputs() {
Integer carbs = SafeParse.stringToInt(editCarbs.getText());
if (carbs > maxCarbs) {
editCarbs.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.carbsconstraintapplied));
}
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
if (insulin > maxInsulin) {
editInsulin.setValue(0d);
ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.bolusconstraintapplied));
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.overview_newtreatment_dialog, container, false);
view.findViewById(R.id.ok).setOnClickListener(this);
view.findViewById(R.id.cancel).setOnClickListener(this);
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
maxCarbs = MainApp.getConstraintChecker().getMaxCarbsAllowed().value();
maxInsulin = MainApp.getConstraintChecker().getMaxBolusAllowed().value();
editCarbs = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_carbsamount);
editInsulin = (NumberPicker) view.findViewById(R.id.treatments_newtreatment_insulinamount);
editCarbs.setParams(0d, 0d, (double) maxCarbs, 1d, new DecimalFormat("0"), false, view.findViewById(R.id.ok), textWatcher);
editInsulin.setParams(0d, 0d, maxInsulin, ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().bolusStep, DecimalFormatter.pumpSupportedBolusFormat(), false, view.findViewById(R.id.ok), textWatcher);
recordOnlyCheckbox = (CheckBox) view.findViewById(R.id.newtreatment_record_only);
setCancelable(true);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
@Override
public synchronized void onClick(View view) {
switch (view.getId()) {
case R.id.ok:
if (okClicked) {
log.debug("guarding: ok already clicked");
dismiss();
return;
}
okClicked = true;
try {
final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
if (pump == null)
return;
Double insulin = SafeParse.stringToDouble(editInsulin.getText());
final Integer carbs = SafeParse.stringToInt(editCarbs.getText());
String confirmMessage = MainApp.gs(R.string.entertreatmentquestion) + "<br/>";
Double insulinAfterConstraints = MainApp.getConstraintChecker().applyBolusConstraints(new Constraint<>(insulin)).value();
Integer carbsAfterConstraints = MainApp.getConstraintChecker().applyCarbsConstraints(new Constraint<>(carbs)).value();
if (insulin > 0) {
confirmMessage += MainApp.gs(R.string.bolus) + ": " + "<font color='" + MainApp.gc(R.color.bolus) + "'>" + DecimalFormatter.toPumpSupportedBolus(insulinAfterConstraints) + "U" + "</font>";
if (recordOnlyCheckbox.isChecked()) {
confirmMessage += "<br/><font color='" + MainApp.gc(R.color.warning) + "'>" + MainApp.gs(R.string.bolusrecordedonly) + "</font>";
}
if (Math.abs(insulinAfterConstraints - insulin) > pump.getPumpDescription().pumpType.determineCorrectBolusStepSize(insulinAfterConstraints) || !Objects.equals(carbsAfterConstraints, carbs))
confirmMessage += "<br/>" + MainApp.gs(R.string.bolusconstraintappliedwarning, MainApp.gc(R.color.warning), insulin, insulinAfterConstraints);
}
if (carbsAfterConstraints > 0)
confirmMessage += "<br/>" + MainApp.gs(R.string.carbs) + ": " + "<font color='" + MainApp.gc(R.color.carbs) + "'>" + carbsAfterConstraints + "g" + "</font>";
final double finalInsulinAfterConstraints = insulinAfterConstraints;
final int finalCarbsAfterConstraints = carbsAfterConstraints;
final Context context = getContext();
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(MainApp.gs(R.string.confirmation));
builder.setMessage(Html.fromHtml(confirmMessage));
builder.setPositiveButton(MainApp.gs(R.string.ok), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
synchronized (builder) {
if (accepted) {
log.debug("guarding: already accepted");
return;
}
accepted = true;
if (finalInsulinAfterConstraints > 0 || finalCarbsAfterConstraints > 0) {
DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo();
if (finalInsulinAfterConstraints == 0)
detailedBolusInfo.eventType = CareportalEvent.CARBCORRECTION;
if (finalCarbsAfterConstraints == 0)
detailedBolusInfo.eventType = CareportalEvent.CORRECTIONBOLUS;
detailedBolusInfo.insulin = finalInsulinAfterConstraints;
detailedBolusInfo.carbs = finalCarbsAfterConstraints;
detailedBolusInfo.context = context;
detailedBolusInfo.source = Source.USER;
if (!(recordOnlyCheckbox.isChecked() && (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().storesCarbInfo))) {
ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, new Callback() {
@Override
public void run() {
if (!result.success) {
Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class);
i.putExtra("soundid", R.raw.boluserror);
i.putExtra("status", result.comment);
i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror));
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MainApp.instance().startActivity(i);
}
}
});
} else {
TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false);
}
}
}
}
});
builder.setNegativeButton(MainApp.gs(R.string.cancel), null);
builder.show();
dismiss();
} catch (Exception e) {
log.error("Unhandled exception", e);
}
break;
case R.id.cancel:
dismiss();
break;
}
}
}

View file

@ -21,7 +21,7 @@ import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.general.nsclient.broadcasts.BroadcastAckAlarm;
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin;
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
import info.nightscout.androidaps.utils.DateUtil;
@ -93,7 +93,7 @@ public class NotificationRecyclerViewAdapter extends RecyclerView.Adapter<Notifi
Notification notification = (Notification) v.getTag();
RxBus.INSTANCE.send(new EventDismissNotification(notification.id));
if (notification.nsAlarm != null) {
BroadcastAckAlarm.handleClearAlarm(notification.nsAlarm, MainApp.instance().getApplicationContext(), 60 * 60 * 1000L);
NSClientPlugin.getPlugin().handleClearAlarm(notification.nsAlarm, 60 * 60 * 1000L);
}
// Adding current time to snooze if we got staleData
if (L.isEnabled(L.NOTIFICATION))

View file

@ -5,6 +5,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import dagger.android.support.DaggerFragment
import info.nightscout.androidaps.R
import info.nightscout.androidaps.plugins.bus.RxBus.toObservable
import info.nightscout.androidaps.plugins.general.smsCommunicator.events.EventSmsCommunicatorUpdateGui
@ -15,11 +16,15 @@ import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.smscommunicator_fragment.*
import java.util.*
import javax.inject.Inject
import kotlin.math.max
class SmsCommunicatorFragment : Fragment() {
class SmsCommunicatorFragment : DaggerFragment() {
private val disposable = CompositeDisposable()
@Inject
lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.smscommunicator_fragment, container, false)
@ -47,12 +52,12 @@ class SmsCommunicatorFragment : Fragment() {
return (object1.date - object2.date).toInt()
}
}
Collections.sort(SmsCommunicatorPlugin.messages, CustomComparator())
Collections.sort(smsCommunicatorPlugin.messages, CustomComparator())
val messagesToShow = 40
val start = max(0, SmsCommunicatorPlugin.messages.size - messagesToShow)
val start = max(0, smsCommunicatorPlugin.messages.size - messagesToShow)
var logText = ""
for (x in start until SmsCommunicatorPlugin.messages.size) {
val sms = SmsCommunicatorPlugin.messages[x]
for (x in start until smsCommunicatorPlugin.messages.size) {
val sms = smsCommunicatorPlugin.messages[x]
when {
sms.ignored -> {
logText += DateUtil.timeString(sms.date) + " &lt;&lt;&lt; " + "" + sms.phoneNumber + " <b>" + sms.text + "</b><br>"

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