From 1ca04777c3289f43aa735c014f525726ebf0325f Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Tue, 28 Dec 2021 22:54:04 +0000 Subject: [PATCH 01/40] - combo changes to display error count --- .../plugins/pump/combo/ComboFragment.java | 57 +++++++++- .../plugins/pump/combo/ComboPlugin.java | 5 + .../pump/combo/data/ComboErrorUtil.java | 106 ++++++++++++++++++ .../plugins/pump/combo/data/ErrorState.java | 17 +++ .../combo/ruffyscripter/RuffyScripter.java | 19 ++++ .../main/res/layout/combopump_fragment.xml | 49 ++++++++ combo/src/main/res/values/arrays.xml | 14 +++ combo/src/main/res/values/strings.xml | 17 ++- combo/src/main/res/xml/pref_combo.xml | 22 ++++ 9 files changed, 304 insertions(+), 2 deletions(-) create mode 100755 combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ComboErrorUtil.java create mode 100755 combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ErrorState.java create mode 100755 combo/src/main/res/values/arrays.xml create mode 100755 combo/src/main/res/xml/pref_combo.xml diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboFragment.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboFragment.java index 8faedd6950..6c760c5297 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboFragment.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboFragment.java @@ -8,6 +8,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; +import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; @@ -19,6 +20,7 @@ import dagger.android.support.DaggerFragment; import info.nightscout.androidaps.combo.R; import info.nightscout.androidaps.interfaces.CommandQueue; import info.nightscout.androidaps.plugins.bus.RxBus; +import info.nightscout.androidaps.plugins.pump.combo.data.ComboErrorUtil; import info.nightscout.androidaps.plugins.pump.combo.events.EventComboPumpUpdateGUI; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.PumpState; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.Bolus; @@ -53,6 +55,12 @@ public class ComboFragment extends DaggerFragment { private TextView bolusCount; private TextView tbrCount; + private View errorCountDelimiter; + private LinearLayout errorCountLayout; + private TextView errorCountLabel; + private TextView errorCountDots; + private TextView errorCountValue; + @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -69,6 +77,12 @@ public class ComboFragment extends DaggerFragment { bolusCount = view.findViewById(R.id.combo_bolus_count); tbrCount = view.findViewById(R.id.combo_tbr_count); + errorCountDelimiter = view.findViewById(R.id.combo_connection_error_delimiter); + errorCountLayout = view.findViewById(R.id.combo_connection_error_layout); + errorCountLabel = view.findViewById(R.id.combo_connection_error_label); + errorCountDots = view.findViewById(R.id.combo_connection_error_dots); + errorCountValue = view.findViewById(R.id.combo_connection_error_value); + refreshButton = view.findViewById(R.id.combo_refresh_button); refreshButton.setOnClickListener(v -> { refreshButton.setEnabled(false); @@ -240,6 +254,47 @@ public class ComboFragment extends DaggerFragment { // stats bolusCount.setText(String.valueOf(comboPlugin.getBolusesDelivered())); tbrCount.setText(String.valueOf(comboPlugin.getTbrsSet())); + + updateErrorDisplay(false); + } else { + updateErrorDisplay(true); } } -} \ No newline at end of file + + private void updateErrorDisplay(boolean forceHide) { + int errorCount = -1; + + ComboErrorUtil errorUtil = ComboErrorUtil.getInstance(); + + if (!forceHide) { + ComboErrorUtil.DisplayType displayType = errorUtil.getDisplayType(); + + if (displayType== ComboErrorUtil.DisplayType.ON_ERROR || displayType== ComboErrorUtil.DisplayType.ALWAYS) { + int errorCountInternal = errorUtil.getErrorCount(); + + if (errorCountInternal>0) { + errorCount = errorCountInternal; + } else if (displayType== ComboErrorUtil.DisplayType.ALWAYS) { + errorCount = 0; + } + } + } + + if (errorCount >=0) { + errorCountDelimiter.setVisibility(View.VISIBLE); + errorCountLayout.setVisibility(View.VISIBLE); + errorCountLabel.setVisibility(View.VISIBLE); + errorCountDots.setVisibility(View.VISIBLE); + errorCountValue.setVisibility(View.VISIBLE); + errorCountValue.setText(errorCount==0 ? + "-" : + ""+errorCount); + } else { + errorCountDelimiter.setVisibility(View.GONE); + errorCountLayout.setVisibility(View.GONE); + errorCountLabel.setVisibility(View.GONE); + errorCountDots.setVisibility(View.GONE); + errorCountValue.setVisibility(View.GONE); + } + } +} diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java index 72f9040087..29d38d54f3 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java @@ -38,6 +38,7 @@ import info.nightscout.androidaps.interfaces.Pump; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpPluginBase; import info.nightscout.androidaps.interfaces.PumpSync; +import info.nightscout.androidaps.plugins.pump.combo.data.ComboErrorUtil; import info.nightscout.shared.logging.AAPSLogger; import info.nightscout.shared.logging.LTag; import info.nightscout.androidaps.plugins.bus.RxBus; @@ -161,6 +162,7 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints { .pluginIcon(R.drawable.ic_combo_128) .pluginName(R.string.combopump) .shortName(R.string.combopump_shortname) + .preferencesId(R.xml.pref_combo) .description(R.string.description_pump_combo), injector, aapsLogger, rh, commandQueue ); @@ -172,6 +174,9 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints { this.pumpSync = pumpSync; this.dateUtil = dateUtil; + ComboErrorUtil.getInstance().setSP(sp); + ComboErrorUtil.getInstance().clearErrors(); + pumpDescription.fillFor(PumpType.ACCU_CHEK_COMBO); } diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ComboErrorUtil.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ComboErrorUtil.java new file mode 100755 index 0000000000..79ce7b71dc --- /dev/null +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ComboErrorUtil.java @@ -0,0 +1,106 @@ +package info.nightscout.androidaps.plugins.pump.combo.data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import info.nightscout.androidaps.combo.R; +import info.nightscout.shared.sharedPreferences.SP; + +/** + * Created by andy on 3/17/18. + */ +public class ComboErrorUtil { + + private SP sp; + + Map> errorMap = new HashMap<>(); + + private static final ComboErrorUtil comboDataUtil = new ComboErrorUtil(); + + private ComboErrorUtil() { + } + + public static ComboErrorUtil getInstance() { + return comboDataUtil; + } + + public void setSP(SP sp) { + this.sp = sp; + } + + public void addError(Exception exception) { + String exceptionMsg = exception.getMessage(); + + if (!errorMap.containsKey(exceptionMsg)) { + List list = new ArrayList<>(); + list.add(createErrorState(exception)); + + errorMap.put(exceptionMsg, list); + } else { + errorMap.get(exceptionMsg).add(createErrorState(exception)); + } + + updateErrorCount(); + } + + + private void updateErrorCount() { + int errorCount = 0; + + if (!isErrorPresent()) { + for (List errorStates : errorMap.values()) { + errorCount += errorStates.size(); + } + } + + if (errorCount==0) { + if (sp.contains(R.string.key_combo_error_count)) { + sp.remove(R.string.key_combo_error_count); + } + } else { + sp.putInt(R.string.key_combo_error_count, errorCount); + } + } + + private ErrorState createErrorState(Exception exception) { + ErrorState errorState = new ErrorState(); + errorState.setException(exception); + errorState.setTimeInMillis(System.currentTimeMillis()); + + return errorState; + } + + public void clearErrors() { + if (errorMap != null) + this.errorMap.clear(); + else + this.errorMap = new HashMap<>(); + + if (sp.contains(R.string.key_combo_error_count)) { + sp.remove(R.string.key_combo_error_count); + } + } + + public boolean isErrorPresent() { + return !this.errorMap.isEmpty(); + } + + public int getErrorCount() { + return sp.contains(R.string.key_combo_error_count) ? + sp.getInt(R.string.key_combo_error_count, -1) : -1; + } + + public DisplayType getDisplayType() { + String displayTypeString = sp.getString(R.string.key_show_comm_error_count, "ON_ERROR"); + return DisplayType.valueOf(displayTypeString); + } + + public enum DisplayType { + NEVER, + ON_ERROR, + ALWAYS + } + +} diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ErrorState.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ErrorState.java new file mode 100755 index 0000000000..ec00441309 --- /dev/null +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ErrorState.java @@ -0,0 +1,17 @@ +package info.nightscout.androidaps.plugins.pump.combo.data; + +public class ErrorState { + + private Exception exception; + private long timeInMillis; + + + public void setException(Exception exception) { + this.exception = exception; + } + + + public void setTimeInMillis(long timeInMillis) { + this.timeInMillis = timeInMillis; + } +} diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/RuffyScripter.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/RuffyScripter.java index f5aedff356..155c9f45ae 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/RuffyScripter.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/RuffyScripter.java @@ -25,6 +25,7 @@ import java.util.Date; import java.util.List; import java.util.Objects; +import info.nightscout.androidaps.plugins.pump.combo.data.ComboErrorUtil; import info.nightscout.shared.logging.StacktraceLoggerWrapper; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands.ReadQuickInfoCommand; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.PumpHistoryRequest; @@ -188,6 +189,14 @@ public class RuffyScripter implements RuffyCommands { } } + private void addError(Exception e) { + try { + ComboErrorUtil.getInstance().addError(e); + } catch (Exception ex) { + log.error("Combo data util problem." + ex.getMessage(), ex); + } + } + @Override public synchronized void disconnect() { if (ruffyService == null) { @@ -196,10 +205,16 @@ public class RuffyScripter implements RuffyCommands { try { log.debug("Disconnecting"); ruffyService.doRTDisconnect(); + try { + ComboErrorUtil.getInstance().clearErrors(); + } catch (Exception ex) { + log.error("Combo data util problem." + ex.getMessage(), ex); + } } catch (RemoteException e) { // ignore } catch (Exception e) { log.warn("Disconnect not happy", e); + addError(e); } } @@ -262,9 +277,11 @@ public class RuffyScripter implements RuffyCommands { log.debug("Executing " + cmd + " took " + (cmdEndTime - cmdStartTime) + "ms"); } catch (CommandException e) { log.info("CommandException running command", e); + addError(e); cmd.getResult().success = false; } catch (Exception e) { log.error("Unexpected exception running cmd", e); + addError(e); cmd.getResult().success = false; } }, cmd.getClass().getSimpleName()); @@ -329,10 +346,12 @@ public class RuffyScripter implements RuffyCommands { } catch (CommandException e) { log.error("CommandException while executing command", e); PumpState pumpState = recoverFromCommandFailure(); + addError(e); return activeCmd.getResult().success(false).state(pumpState); } catch (Exception e) { log.error("Unexpected exception communication with ruffy", e); PumpState pumpState = recoverFromCommandFailure(); + addError(e); return activeCmd.getResult().success(false).state(pumpState); } finally { Menu menu = this.currentMenu; diff --git a/combo/src/main/res/layout/combopump_fragment.xml b/combo/src/main/res/layout/combopump_fragment.xml index 8e13a5fb8f..dcc1139a27 100644 --- a/combo/src/main/res/layout/combopump_fragment.xml +++ b/combo/src/main/res/layout/combopump_fragment.xml @@ -462,6 +462,55 @@ + + + + + + + + + + + + + + + @string/combo_error_display_never + @string/combo_error_display_error + @string/combo_error_display_always + + + + @string/key_combo_error_display_never + @string/key_combo_error_display_error + @string/key_combo_error_display_always + + \ No newline at end of file diff --git a/combo/src/main/res/values/strings.xml b/combo/src/main/res/values/strings.xml index dd844055ee..314a3e468c 100644 --- a/combo/src/main/res/values/strings.xml +++ b/combo/src/main/res/values/strings.xml @@ -57,4 +57,19 @@ combo_pump_serial combo_tbrs_set combo_boluses_delivered - \ No newline at end of file + Comm. Error count + combo_error_count + combo_name_settings + show_error_count + Show comm. error count + Shows count of errors, when communicating with Ruffy. In most cases number higher than 0 denotes, Ruffy communication problems (restart might be needed). + + Never + When Error + Always + + NEVER + ON_ERROR + ALWAYS + + diff --git a/combo/src/main/res/xml/pref_combo.xml b/combo/src/main/res/xml/pref_combo.xml new file mode 100755 index 0000000000..601bc4f62f --- /dev/null +++ b/combo/src/main/res/xml/pref_combo.xml @@ -0,0 +1,22 @@ + + + + + + + + + + \ No newline at end of file From e969b509cc4fefd5e522ec4847c67846acf31a33 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Feb 2022 08:08:33 +0000 Subject: [PATCH 02/40] Bump wearableVersion from 2.8.1 to 2.9.0 Bumps `wearableVersion` from 2.8.1 to 2.9.0. Updates `wearable` from 2.8.1 to 2.9.0 Updates `wearable` from 2.8.1 to 2.9.0 --- updated-dependencies: - dependency-name: com.google.android.wearable:wearable dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: com.google.android.support:wearable dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- wear/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wear/build.gradle b/wear/build.gradle index 34d1a75048..bb760a4ab2 100644 --- a/wear/build.gradle +++ b/wear/build.gradle @@ -21,7 +21,7 @@ apply from: "${project.rootDir}/gradle/jacoco_global.gradle" ext { - wearableVersion = "2.8.1" + wearableVersion = "2.9.0" // playServicesWearable 17.1.0 breaks test playServicesWearable = "17.0.0" } From 0aa34a3fb493f0d59bd1ed22fafc70d0679362d0 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 17 Feb 2022 22:16:10 +0100 Subject: [PATCH 03/40] 3.0.0.1-dev-a --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index cc26a49966..afd6151263 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -109,7 +109,7 @@ android { defaultConfig { multiDexEnabled true versionCode 1500 - version "3.0.0.1-dev" + version "3.0.0.1-dev-a" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' From dc1706fde774ef75ed089da5457c0f8f33560796 Mon Sep 17 00:00:00 2001 From: Philoul Date: Thu, 17 Feb 2022 22:26:12 +0100 Subject: [PATCH 04/40] Add TT Icon + Improve IOB/COB --- .../androidaps/dialogs/WizardDialog.kt | 22 ++++++++++++++----- .../main/res/drawable/cb_background_tt.xml | 7 ++++++ .../main/res/drawable/checkbox_tt_icon.xml | 4 ++++ app/src/main/res/layout/dialog_wizard.xml | 14 ++++++++++++ 4 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 app/src/main/res/drawable/cb_background_tt.xml create mode 100644 app/src/main/res/drawable/checkbox_tt_icon.xml diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt index 83aff0201f..d04d8c709a 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt @@ -175,9 +175,10 @@ class WizardDialog : DaggerDialogFragment() { dismiss() } binding.bgCheckboxIcon.setOnClickListener { binding.bgCheckbox.isChecked = !binding.bgCheckbox.isChecked } + binding.ttCheckboxIcon.setOnClickListener { binding.ttCheckbox.isChecked = !binding.ttCheckbox.isChecked } binding.trendCheckboxIcon.setOnClickListener { binding.bgTrendCheckbox.isChecked = !binding.bgTrendCheckbox.isChecked } binding.cobCheckboxIcon.setOnClickListener { binding.cobCheckbox.isChecked = !binding.cobCheckbox.isChecked; processCobCheckBox(); } - binding.iobCheckboxIcon.setOnClickListener { if (!binding.cobCheckbox.isChecked) binding.iobCheckbox.isChecked = !binding.iobCheckbox.isChecked } + binding.iobCheckboxIcon.setOnClickListener { binding.iobCheckbox.isChecked = !binding.iobCheckbox.isChecked; processIobCheckBox(); } // cancel button binding.okcancel.cancel.setOnClickListener { aapsLogger.debug(LTag.APS, "Dialog canceled: ${this.javaClass.name}") @@ -265,35 +266,42 @@ class WizardDialog : DaggerDialogFragment() { private fun onCheckedChanged(buttonView: CompoundButton, @Suppress("UNUSED_PARAMETER") state: Boolean) { saveCheckedStates() binding.ttCheckbox.isEnabled = binding.bgCheckbox.isChecked && repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing + binding.ttCheckboxIcon.visibility = binding.ttCheckbox.isEnabled.toVisibility() if (buttonView.id == binding.cobCheckbox.id) processCobCheckBox() + if (buttonView.id == binding.iobCheckbox.id) + processIobCheckBox() processEnabledIcons() calculateInsulin() } private fun processCobCheckBox() { if (binding.cobCheckbox.isChecked) { - binding.iobCheckbox.isEnabled = false - binding.iobCheckboxIcon.isEnabled = false binding.iobCheckbox.isChecked = true - } else { - binding.iobCheckbox.isEnabled = true - binding.iobCheckboxIcon.isEnabled = true + } + } + + private fun processIobCheckBox() { + if (!binding.iobCheckbox.isChecked) { + binding.cobCheckbox.isChecked = false } } private fun processEnabledIcons() { binding.bgCheckboxIcon.isChecked = binding.bgCheckbox.isChecked + binding.ttCheckboxIcon.isChecked = binding.ttCheckbox.isChecked binding.trendCheckboxIcon.isChecked = binding.bgTrendCheckbox.isChecked binding.iobCheckboxIcon.isChecked = binding.iobCheckbox.isChecked binding.cobCheckboxIcon.isChecked = binding.cobCheckbox.isChecked binding.bgCheckboxIcon.alpha = if (binding.bgCheckbox.isChecked) 1.0f else 0.2f + binding.ttCheckboxIcon.alpha = if (binding.ttCheckbox.isChecked) 1.0f else 0.2f binding.trendCheckboxIcon.alpha = if (binding.bgTrendCheckbox.isChecked) 1.0f else 0.2f binding.iobCheckboxIcon.alpha = if (binding.iobCheckbox.isChecked) 1.0f else 0.2f binding.cobCheckboxIcon.alpha = if (binding.cobCheckbox.isChecked) 1.0f else 0.2f binding.bgCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() + binding.ttCheckboxIcon.visibility = (binding.calculationCheckbox.isChecked.not() && binding.ttCheckbox.isEnabled).toVisibility() binding.trendCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() binding.iobCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() binding.cobCheckboxIcon.visibility = binding.calculationCheckbox.isChecked.not().toVisibility() @@ -345,7 +353,9 @@ class WizardDialog : DaggerDialogFragment() { // Set BG if not old binding.bgInput.value = iobCobCalculator.ads.actualBg()?.valueToUnits(units) ?: 0.0 + binding.ttCheckbox.isEnabled = repository.getTemporaryTargetActiveAt(dateUtil.now()).blockingGet() is ValueWrapper.Existing + binding.ttCheckboxIcon.visibility = binding.ttCheckbox.isEnabled.toVisibility() // IOB calculation val bolusIob = iobCobCalculator.calculateIobFromBolus().round() diff --git a/app/src/main/res/drawable/cb_background_tt.xml b/app/src/main/res/drawable/cb_background_tt.xml new file mode 100644 index 0000000000..291b9f535e --- /dev/null +++ b/app/src/main/res/drawable/cb_background_tt.xml @@ -0,0 +1,7 @@ + + + + diff --git a/app/src/main/res/drawable/checkbox_tt_icon.xml b/app/src/main/res/drawable/checkbox_tt_icon.xml new file mode 100644 index 0000000000..2c3522ae2b --- /dev/null +++ b/app/src/main/res/drawable/checkbox_tt_icon.xml @@ -0,0 +1,4 @@ + + + + diff --git a/app/src/main/res/layout/dialog_wizard.xml b/app/src/main/res/layout/dialog_wizard.xml index 108808e800..d228923681 100644 --- a/app/src/main/res/layout/dialog_wizard.xml +++ b/app/src/main/res/layout/dialog_wizard.xml @@ -263,6 +263,20 @@ android:checked="true" android:contentDescription="@string/treatments_wizard_bg_label" /> + + Date: Thu, 17 Feb 2022 23:35:31 +0100 Subject: [PATCH 05/40] fix rh gs with empty args --- .../utils/resources/ResourceHelperImplementation.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperImplementation.kt b/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperImplementation.kt index b21285bc43..7224b4ec00 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperImplementation.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperImplementation.kt @@ -20,20 +20,21 @@ import javax.inject.Inject */ class ResourceHelperImplementation @Inject constructor(private val context: Context, private val fabricPrivacy: FabricPrivacy) : ResourceHelper { - override fun gs(@StringRes id: Int): String = gs(id, null) + override fun gs(@StringRes id: Int): String = context.getString(id) override fun gs(@StringRes id: Int, vararg args: Any?) : String { return try { context.getString(id, *args) } catch (exception: Exception) { - val resourceName = context.resources.getResourceEntryName(id); + val resourceName = context.resources.getResourceEntryName(id) + val resourceValue = context.getString(id) val currentLocale: Locale = context.resources.configuration.locale - fabricPrivacy.logMessage("Failed to get string for resource $resourceName ($id) for locale $currentLocale with args ${args.map{it.toString()}}") + fabricPrivacy.logMessage("Failed to get string for resource $resourceName ($id) '$resourceValue' for locale $currentLocale with args ${args.map{it.toString()}}") fabricPrivacy.logException(exception) try { gsNotLocalised(id, *args) } catch (exceptionNonLocalized: Exception) { - fabricPrivacy.logMessage("Fallback failed to get string for resource $resourceName ($id) with args ${args.map { it.toString() }}") + fabricPrivacy.logMessage("Fallback failed to get string for resource $resourceName ($id) '$resourceValue' with args ${args.map { it.toString() }}") fabricPrivacy.logException(exceptionNonLocalized) "FAILED to get string $resourceName" } From f89b05dbccfa328e023b2e679e0286f2813d64f7 Mon Sep 17 00:00:00 2001 From: swissalpine Date: Fri, 18 Feb 2022 10:39:46 +0100 Subject: [PATCH 06/40] Background images needs another sizing Sorry for the renewed PR - but I was not aware that the size ratios of the background images differ from the "normal" images. --- app/src/main/res/layout/dialog_wizard.xml | 33 ++++++++++++----------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/app/src/main/res/layout/dialog_wizard.xml b/app/src/main/res/layout/dialog_wizard.xml index 108808e800..ba35d9a31a 100644 --- a/app/src/main/res/layout/dialog_wizard.xml +++ b/app/src/main/res/layout/dialog_wizard.xml @@ -255,10 +255,10 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:paddingStart="5dp" - android:paddingEnd="5dp" - android:scaleX="0.7" - android:scaleY="0.7" + android:paddingStart="10dp" + android:paddingEnd="10dp" + android:scaleX="1.4" + android:scaleY="1.4" android:button="@drawable/checkbox_bg_icon" android:checked="true" android:contentDescription="@string/treatments_wizard_bg_label" /> @@ -268,10 +268,10 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:paddingStart="5dp" - android:paddingEnd="5dp" - android:scaleX="0.7" - android:scaleY="0.7" + android:paddingStart="10dp" + android:paddingEnd="10dp" + android:scaleX="1.4" + android:scaleY="1.4" android:button="@drawable/checkbox_trend_icon" android:checked="true" android:contentDescription="@string/bg_trend_label" /> @@ -281,10 +281,10 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:paddingStart="5dp" - android:paddingEnd="5dp" - android:scaleX="0.9" - android:scaleY="0.9" + android:paddingStart="10dp" + android:paddingEnd="10dp" + android:scaleX="1.4" + android:scaleY="1.4" android:button="@drawable/checkbox_iob_icon" android:checked="true" android:contentDescription="@string/iob" /> @@ -294,14 +294,15 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" - android:paddingStart="5dp" - android:paddingEnd="5dp" - android:scaleX="0.7" - android:scaleY="0.7" + android:paddingStart="0dp" + android:paddingEnd="0dp" + android:scaleX="1.6" + android:scaleY="1.6" android:button="@drawable/checkbox_cob_icon" android:checked="true" android:contentDescription="@string/treatments_wizard_cob_label" /> + Date: Fri, 18 Feb 2022 11:04:05 +0100 Subject: [PATCH 07/40] Some space at the top --- app/src/main/res/layout/dialog_wizard.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/layout/dialog_wizard.xml b/app/src/main/res/layout/dialog_wizard.xml index ba35d9a31a..c312530c52 100644 --- a/app/src/main/res/layout/dialog_wizard.xml +++ b/app/src/main/res/layout/dialog_wizard.xml @@ -245,7 +245,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center|center_vertical" - android:layout_marginTop="0dp" + android:layout_marginTop="5dp" android:background="@android:color/transparent" android:orientation="horizontal" android:padding="0dp"> From 2eb5a4dc27de4524cfb53e2184edd50b0ca50fc5 Mon Sep 17 00:00:00 2001 From: Edward Robinson Date: Fri, 18 Feb 2022 11:35:11 -0500 Subject: [PATCH 08/40] Making it so that the percentage increments by 5% each time rather than 1% --- .../java/info/nightscout/androidaps/dialogs/WizardDialog.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt index 83aff0201f..db15ac4946 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt @@ -146,7 +146,7 @@ class WizardDialog : DaggerDialogFragment() { if (correctionPercent) { calculatedPercentage = sp.getInt(R.string.key_boluswizard_percentage, 100).toDouble() - binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher) + binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 5.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher) binding.correctionInput.value = calculatedPercentage binding.correctionUnit.text = "%" } else { @@ -212,7 +212,7 @@ class WizardDialog : DaggerDialogFragment() { binding.correctionUnit.text = if (isChecked) "%" else rh.gs(R.string.insulin_unit_shortname) correctionPercent = binding.correctionPercent.isChecked if (correctionPercent) { - binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 1.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher) + binding.correctionInput.setParams(calculatedPercentage, 10.0, 200.0, 5.0, DecimalFormat("0"), false, binding.okcancel.ok, textWatcher) binding.correctionInput.customContentDescription = rh.gs(R.string.a11_correction_percentage) } else { binding.correctionInput.setParams( From a2c6db4b572245895b7f94332d3f2ed14b5af910 Mon Sep 17 00:00:00 2001 From: swissalpine Date: Sat, 19 Feb 2022 00:56:31 +0100 Subject: [PATCH 09/40] Centered Icons @ Philoul: Thanks for the suggestion! --- app/src/main/res/layout/dialog_wizard.xml | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/app/src/main/res/layout/dialog_wizard.xml b/app/src/main/res/layout/dialog_wizard.xml index c312530c52..25eb86dd89 100644 --- a/app/src/main/res/layout/dialog_wizard.xml +++ b/app/src/main/res/layout/dialog_wizard.xml @@ -245,7 +245,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center|center_vertical" - android:layout_marginTop="5dp" + android:layout_marginTop="10dp" android:background="@android:color/transparent" android:orientation="horizontal" android:padding="0dp"> @@ -254,9 +254,8 @@ android:id="@+id/bg_checkbox_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:paddingStart="10dp" - android:paddingEnd="10dp" + android:layout_marginLeft="15dp" + android:layout_marginRight="15dp" android:scaleX="1.4" android:scaleY="1.4" android:button="@drawable/checkbox_bg_icon" @@ -267,9 +266,8 @@ android:id="@+id/trend_checkbox_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:paddingStart="10dp" - android:paddingEnd="10dp" + android:layout_marginLeft="15dp" + android:layout_marginRight="15dp" android:scaleX="1.4" android:scaleY="1.4" android:button="@drawable/checkbox_trend_icon" @@ -280,9 +278,8 @@ android:id="@+id/iob_checkbox_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:paddingStart="10dp" - android:paddingEnd="10dp" + android:layout_marginLeft="15dp" + android:layout_marginRight="15dp" android:scaleX="1.4" android:scaleY="1.4" android:button="@drawable/checkbox_iob_icon" @@ -293,16 +290,14 @@ android:id="@+id/cob_checkbox_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:paddingStart="0dp" - android:paddingEnd="0dp" + android:layout_marginLeft="15dp" + android:layout_marginRight="15dp" android:scaleX="1.6" android:scaleY="1.6" android:button="@drawable/checkbox_cob_icon" android:checked="true" android:contentDescription="@string/treatments_wizard_cob_label" /> - Date: Sun, 20 Feb 2022 11:49:18 +0100 Subject: [PATCH 10/40] Typo in source translator for SMS --- .../main/java/info/nightscout/androidaps/utils/Translator.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/info/nightscout/androidaps/utils/Translator.kt b/core/src/main/java/info/nightscout/androidaps/utils/Translator.kt index 39593aa8d0..d680f5e3f3 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/Translator.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/Translator.kt @@ -287,7 +287,7 @@ class Translator @Inject internal constructor( Sources.Loop -> rh.gs(R.string.loop) Sources.NSClient -> rh.gs(R.string.ns) Sources.Pump -> rh.gs(R.string.pump) - Sources.SMS -> rh.gs(R.string.smb_shortname) + Sources.SMS -> rh.gs(R.string.sms) Sources.Wear -> rh.gs(R.string.wear) Sources.Unknown -> rh.gs(R.string.unknown) From c216e41e1cc840fa43aef3b3c8f40c858b3c4ee9 Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 20 Feb 2022 11:53:06 +0100 Subject: [PATCH 11/40] New shortname for Dynamic ISF plugin --- .../aps/openAPSSMBDynamicISF/OpenAPSSMBDynamicISFPlugin.kt | 1 + app/src/main/res/values/strings.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/OpenAPSSMBDynamicISFPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/OpenAPSSMBDynamicISFPlugin.kt index 8c80b90738..0187b85ece 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/OpenAPSSMBDynamicISFPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/OpenAPSSMBDynamicISFPlugin.kt @@ -65,6 +65,7 @@ class OpenAPSSMBDynamicISFPlugin @Inject constructor( pluginDescription .pluginName(R.string.openaps_smb_dynamic_isf) .description(R.string.description_smb_dynamic_isf) + .shortName(R.string.dynisf_shortname) .setDefault(false) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fa3550bae6..5ca1c26ea7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -335,6 +335,7 @@ CONF LOOP OAPS + DYNISF LP HOME VPUMP From 8b749284228048f93b69fcabb3645e6a4685d438 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 20 Feb 2022 15:24:21 +0100 Subject: [PATCH 12/40] prevent crash --- .../androidaps/plugins/general/automation/AutomationPlugin.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt b/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt index 42aba423c0..da080d92e7 100644 --- a/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt +++ b/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/AutomationPlugin.kt @@ -278,7 +278,7 @@ class AutomationPlugin @Inject constructor( @Synchronized fun removeIfExists(event: AutomationEvent) { - for (e in automationEvents) { + for (e in automationEvents.reversed()) { if (event.title == e.title) { automationEvents.remove(e) rxBus.send(EventAutomationDataChanged()) @@ -301,6 +301,7 @@ class AutomationPlugin @Inject constructor( @Synchronized fun at(index: Int) = automationEvents[index] + @Synchronized fun size() = automationEvents.size @Synchronized @@ -309,6 +310,7 @@ class AutomationPlugin @Inject constructor( rxBus.send(EventAutomationDataChanged()) } + @Synchronized fun userEvents(): List { val list = mutableListOf() val iterator: MutableIterator = automationEvents.iterator() From b2e3399597b051d1e633d001da1a843ca51c68a9 Mon Sep 17 00:00:00 2001 From: t_j_s Date: Sun, 20 Feb 2022 15:43:45 +0000 Subject: [PATCH 13/40] UPdated code to include rolling 24 hour TDD in TDD calculator; incuding updating the calculation steps code. DYnamic ISF now based off rolling 24 hour TDD instead of estimated daily TDD in midnight to midnight period. --- .../OpenAPSSMBDynamicISF/determine-basal.js | 32 +++++++++---- .../DetermineBasalAdapterSMBDynamicISFJS.kt | 1 + .../androidaps/utils/stats/TddCalculator.kt | 46 +++++++++++++++++++ 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js b/app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js index ce13f03387..d65a328136 100644 --- a/app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js +++ b/app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js @@ -284,18 +284,32 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ else { console.error("Time now is "+now+"; "); } + console.error("++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + console.error("++ Dynamic ISF Beta 1.3 - Based on rolling 24 hours ++"); + console.error("++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + if (meal_data.TDDAIMI7){ var tdd7 = meal_data.TDDAIMI7; + } + else{ + var tdd7 = ((basal * 12)*100)/21; } - else{ - var tdd7 = ((basal * 12)*100)/21; - } - var tdd_pump_now = meal_data.TDDPUMP; - var tdd_pump = ( tdd_pump_now / (now / 24)); - var TDD = (tdd7 * 0.4) + (tdd_pump * 0.6); - console.error("Pump extrapolated TDD = "+tdd_pump+"; "); + console.error("7-day average TDD is: " +tdd7+ "; "); + + + if (meal_data.TDDLast24){ + var tdd_24 = meal_data.TDDLast24; + } + else { + var tdd_24 = (( basal * 24 ) * 2.8); + } + + var TDD = (tdd7 * 0.3) + (tdd_24 * 0.7); + + console.error("Rolling 24 hour TDD = "+tdd_24+"; "); + console.error("Weighted Average TDD = "+TDD"; "); //if (tdd7 > 0){ - if ( tdd_pump > tdd7 && now < 5 || now < 7 && TDD < ( 0.8 * tdd7 ) ){ + /*if ( tdd_pump > tdd7 && now < 5 || now < 7 && TDD < ( 0.8 * tdd7 ) ){ TDD = ( 0.8 * tdd7 ); console.log("Excess or too low insulin from pump so TDD set to "+TDD+" based on 75% of TDD7; "); rT.reason += "TDD: " +TDD+ " due to low or high tdd from pump; "; @@ -316,7 +330,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ else { console.log("TDD 7 ="+tdd7+", TDD Pump ="+tdd_pump+" and TDD = "+TDD+";"); rT.reason += "TDD: " +TDD+ " based on standard pump 60/tdd7 40 split; "; - } + }*/ var variable_sens = (277700 / (TDD * bg)); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt index 950a3e9f26..4a84093b6a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt @@ -260,6 +260,7 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri this.mealData.put("TDDAIMI7", tddCalculator.averageTDD(tddCalculator.calculate(7)).totalAmount) this.mealData.put("TDDPUMP", tddCalculator.calculateDaily().totalAmount) + this.mealData.put("TDDLast24", tddCalculator!!.calculate24Daily().totalAmount) if (constraintChecker.isAutosensModeEnabled().value()) { autosensData.put("ratio", autosensDataRatio) diff --git a/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt b/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt index 0f08ccea8a..fc7cfe2bb0 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt @@ -122,7 +122,53 @@ class TddCalculator @Inject constructor( aapsLogger.debug(LTag.CORE, tdd.toString()) return tdd } + fun calculate24Daily():TotalDailyDose { + val startTime = dateUtil.now() - T.hours(hour = 24).msecs() + val endTime = dateUtil.now() + val tdd = TotalDailyDose(timestamp = startTime) + //val result = TotalDailyDose() + repository.getBolusesDataFromTimeToTime(startTime, endTime, true).blockingGet() + .filter { it.type != Bolus.Type.PRIMING } + .forEach { t -> + //val midnight = MidnightTime.calc(t.timestamp) + //val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight) + tdd.bolusAmount += t.amount + //result.put(midnight, tdd) + } + repository.getCarbsDataFromTimeToTimeExpanded(startTime, endTime, true).blockingGet().forEach { t -> + //val midnight = MidnightTime.calc(t.timestamp) + //val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight) + tdd.carbs += t.amount + //result.put(midnight, tdd) + } + val calculationStep = T.mins(5).msecs() + val tempBasals = iobCobCalculator.getTempBasalIncludingConvertedExtendedForRange(startTime, endTime, calculationStep) + for (t in startTime until endTime step calculationStep) { + //val midnight = MidnightTime.calc(t) + //val tdd = result[midnight] ?: TotalDailyDose(timestamp = midnight) + val tbr = iobCobCalculator.getTempBasalIncludingConvertedExtended(t) + val profile = profileFunction.getProfile(t) ?: continue + val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t) + tdd.basalAmount += absoluteRate / T.mins(5).msecs().toDouble() * calculationStep.toDouble() + + if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) { + // they are not included in TBRs + val eb = iobCobCalculator.getExtendedBolus(t) + val absoluteEbRate = eb?.rate ?: 0.0 + tdd.bolusAmount += absoluteEbRate / T.mins(5).msecs().toDouble() * calculationStep.toDouble() + } + //result.put(midnight, tdd) + } + //for (i in 0 until tdd.size()) { + //val tdd = result.valueAt(i) + tdd.totalAmount = tdd.bolusAmount + tdd.basalAmount + //} + + + aapsLogger.debug(LTag.CORE, tdd.toString()) + return tdd + } fun averageTDD(tdds: LongSparseArray): TotalDailyDose { val totalTdd = TotalDailyDose(timestamp = dateUtil.now()) for (i in 0 until tdds.size()) { From 58d9ce78d7e81c28de497539e80e9a1435f02b1b Mon Sep 17 00:00:00 2001 From: t_j_s Date: Sun, 20 Feb 2022 15:45:32 +0000 Subject: [PATCH 14/40] Noticed typo in console logging line 310. Fixed. --- app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js b/app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js index d65a328136..6d07a6426f 100644 --- a/app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js +++ b/app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js @@ -307,7 +307,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ var TDD = (tdd7 * 0.3) + (tdd_24 * 0.7); console.error("Rolling 24 hour TDD = "+tdd_24+"; "); - console.error("Weighted Average TDD = "+TDD"; "); + console.error("Weighted Average TDD = "+TDD+"; "); //if (tdd7 > 0){ /*if ( tdd_pump > tdd7 && now < 5 || now < 7 && TDD < ( 0.8 * tdd7 ) ){ TDD = ( 0.8 * tdd7 ); From 035e9742afea1452d402ab1f17774af12bbd1cb3 Mon Sep 17 00:00:00 2001 From: t_j_s Date: Sun, 20 Feb 2022 15:58:06 +0000 Subject: [PATCH 15/40] Use of calculation step reverted back to value / 60 * 5, as calculation step method was producing incorrect, very large numbers. --- .../nightscout/androidaps/utils/stats/TddCalculator.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt b/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt index fc7cfe2bb0..34663d0800 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt @@ -103,13 +103,13 @@ class TddCalculator @Inject constructor( val tbr = iobCobCalculator.getTempBasalIncludingConvertedExtended(t) val profile = profileFunction.getProfile(t) ?: continue val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t) - tdd.basalAmount += absoluteRate / T.mins(5).msecs().toDouble() * calculationStep.toDouble() + tdd.basalAmount += absoluteRate / 60.0 * 5.0 if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) { // they are not included in TBRs val eb = iobCobCalculator.getExtendedBolus(t) val absoluteEbRate = eb?.rate ?: 0.0 - tdd.bolusAmount += absoluteEbRate / T.mins(5).msecs().toDouble() * calculationStep.toDouble() + tdd.bolusAmount += absoluteEbRate / 60.0 * 5.0 } //result.put(midnight, tdd) } @@ -150,13 +150,13 @@ class TddCalculator @Inject constructor( val tbr = iobCobCalculator.getTempBasalIncludingConvertedExtended(t) val profile = profileFunction.getProfile(t) ?: continue val absoluteRate = tbr?.convertedToAbsolute(t, profile) ?: profile.getBasal(t) - tdd.basalAmount += absoluteRate / T.mins(5).msecs().toDouble() * calculationStep.toDouble() + tdd.basalAmount += absoluteRate / 60.0 * 5.0 if (!activePlugin.activePump.isFakingTempsByExtendedBoluses) { // they are not included in TBRs val eb = iobCobCalculator.getExtendedBolus(t) val absoluteEbRate = eb?.rate ?: 0.0 - tdd.bolusAmount += absoluteEbRate / T.mins(5).msecs().toDouble() * calculationStep.toDouble() + tdd.bolusAmount += absoluteEbRate / 60.0 * 5.0 } //result.put(midnight, tdd) } From 304edd87ebda8207e705ee3fa8f794a4828a2607 Mon Sep 17 00:00:00 2001 From: t_j_s Date: Sun, 20 Feb 2022 16:06:34 +0000 Subject: [PATCH 16/40] Formatting fixes in sens logic --- .../main/assets/OpenAPSSMBDynamicISF/determine-basal.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js b/app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js index 6d07a6426f..13d66a859f 100644 --- a/app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js +++ b/app/src/main/assets/OpenAPSSMBDynamicISF/determine-basal.js @@ -284,9 +284,11 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ else { console.error("Time now is "+now+"; "); } + console.error(" "); console.error("++++++++++++++++++++++++++++++++++++++++++++++++++++++"); console.error("++ Dynamic ISF Beta 1.3 - Based on rolling 24 hours ++"); console.error("++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + console.error(" "); if (meal_data.TDDAIMI7){ var tdd7 = meal_data.TDDAIMI7; @@ -295,7 +297,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ var tdd7 = ((basal * 12)*100)/21; } console.error("7-day average TDD is: " +tdd7+ "; "); - + console.error(" "); if (meal_data.TDDLast24){ var tdd_24 = meal_data.TDDLast24; @@ -307,7 +309,9 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ var TDD = (tdd7 * 0.3) + (tdd_24 * 0.7); console.error("Rolling 24 hour TDD = "+tdd_24+"; "); + console.error(" "); console.error("Weighted Average TDD = "+TDD+"; "); + console.error(" "); //if (tdd7 > 0){ /*if ( tdd_pump > tdd7 && now < 5 || now < 7 && TDD < ( 0.8 * tdd7 ) ){ TDD = ( 0.8 * tdd7 ); @@ -336,6 +340,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ var variable_sens = (277700 / (TDD * bg)); variable_sens = round(variable_sens,1); console.log("Current sensitivity for predictions is " +variable_sens+" based on current bg"); + console.error(" "); sens = variable_sens; if ( high_temptarget_raises_sensitivity && profile.temptargetSet && target_bg > normalTarget || profile.low_temptarget_lowers_sensitivity && profile.temptargetSet && target_bg < normalTarget ) { @@ -403,7 +408,7 @@ var determine_basal = function determine_basal(glucose_status, currenttemp, iob_ if (iob_data.iob > 0) { var naive_eventualBG = round( bg - (iob_data.iob * sens) ); } else { // if IOB is negative, be more conservative and use the lower of sens, profile.sens - naive_eventualBG = round( bg - (iob_data.iob * Math.min(sens, profile.sens) ) ); + naive_eventualBG = round( bg - (iob_data.iob * sens ) ); } // and adjust it for the deviation above var eventualBG = naive_eventualBG + deviation; From 6a961eb4d8b949ff8564bcd17f0f3b2469e0beda Mon Sep 17 00:00:00 2001 From: swissalpine Date: Sun, 20 Feb 2022 17:24:36 +0100 Subject: [PATCH 17/40] Fix for DynamicISF safety limiter bug https://github.com/nightscout/AndroidAPS/issues/1349 https://github.com/nightscout/AndroidAPS/issues/1346 --- .../androidaps/plugins/constraints/safety/SafetyPlugin.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.kt index cff84db028..bb1dcae6ed 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPlugin.kt @@ -9,6 +9,7 @@ import info.nightscout.androidaps.interfaces.* import info.nightscout.shared.logging.AAPSLogger import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin +import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.OpenAPSSMBDynamicISFPlugin import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification @@ -36,6 +37,7 @@ class SafetyPlugin @Inject constructor( private val constraintChecker: ConstraintChecker, private val openAPSAMAPlugin: OpenAPSAMAPlugin, private val openAPSSMBPlugin: OpenAPSSMBPlugin, + private val OpenAPSSMBDynamicISFPlugin: OpenAPSSMBDynamicISFPlugin, private val sensitivityOref1Plugin: SensitivityOref1Plugin, private val activePlugin: ActivePlugin, private val hardLimits: HardLimits, @@ -188,10 +190,12 @@ class SafetyPlugin @Inject constructor( override fun applyMaxIOBConstraints(maxIob: Constraint): Constraint { val apsMode = sp.getString(R.string.key_aps_mode, "open") - val maxIobPref: Double = if (openAPSSMBPlugin.isEnabled()) sp.getDouble(R.string.key_openapssmb_max_iob, 3.0) else sp.getDouble(R.string.key_openapsma_max_iob, 1.5) + val maxIobPref: Double = if (openAPSSMBPlugin.isEnabled() || OpenAPSSMBDynamicISFPlugin.isEnabled()) sp.getDouble(R.string.key_openapssmb_max_iob, 3.0) else sp.getDouble(R.string + .key_openapsma_max_iob, 1.5) maxIob.setIfSmaller(aapsLogger, maxIobPref, String.format(rh.gs(R.string.limitingiob), maxIobPref, rh.gs(R.string.maxvalueinpreferences)), this) if (openAPSAMAPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobAMA(), String.format(rh.gs(R.string.limitingiob), hardLimits.maxIobAMA(), rh.gs(R.string.hardlimit)), this) if (openAPSSMBPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), String.format(rh.gs(R.string.limitingiob), hardLimits.maxIobSMB(), rh.gs(R.string.hardlimit)), this) + if (OpenAPSSMBDynamicISFPlugin.isEnabled()) maxIob.setIfSmaller(aapsLogger, hardLimits.maxIobSMB(), String.format(rh.gs(R.string.limitingiob), hardLimits.maxIobSMB(), rh.gs(R.string.hardlimit)), this) if (apsMode == "lgs") maxIob.setIfSmaller(aapsLogger, HardLimits.MAX_IOB_LGS, String.format(rh.gs(R.string.limitingiob), HardLimits.MAX_IOB_LGS, rh.gs(R.string.lowglucosesuspend)), this) return maxIob } @@ -207,4 +211,4 @@ class SafetyPlugin @Inject constructor( configuration.storeDouble(R.string.key_treatmentssafety_maxbolus, sp, rh) configuration.storeInt(R.string.key_treatmentssafety_maxcarbs, sp, rh) } -} \ No newline at end of file +} From ad8c2297a01a9165f1e9babc29f63bb9bf46e8f4 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 20 Feb 2022 19:27:01 +0100 Subject: [PATCH 18/40] Combo: cleanup code --- .../DetermineBasalAdapterSMBDynamicISFJS.kt | 2 +- .../androidaps/utils/stats/TddCalculator.kt | 2 +- .../plugins/pump/combo/ComboFragment.java | 3 +- .../plugins/pump/combo/ComboPlugin.java | 15 +- .../pump/combo/data/ComboErrorUtil.java | 106 ---------- .../plugins/pump/combo/data/ComboErrorUtil.kt | 49 +++++ .../plugins/pump/combo/data/ErrorState.java | 17 -- .../combo/ruffyscripter/RuffyScripter.java | 183 +++++++++--------- .../ruffyscripter/commands/BolusCommand.java | 72 +++---- .../commands/CancelTbrCommand.java | 14 +- .../commands/ReadBasalProfileCommand.java | 18 +- .../commands/ReadHistoryCommand.java | 72 ++++--- .../commands/ReadQuickInfoCommand.java | 23 +-- .../commands/SetBasalProfileCommand.java | 27 +-- .../ruffyscripter/commands/SetTbrCommand.java | 43 ++-- .../resources/ResourceHelperImplementation.kt | 2 +- 16 files changed, 296 insertions(+), 352 deletions(-) delete mode 100755 combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ComboErrorUtil.java create mode 100644 combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ComboErrorUtil.kt delete mode 100755 combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ErrorState.java diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt index 4a84093b6a..5bdee7d474 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt @@ -260,7 +260,7 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri this.mealData.put("TDDAIMI7", tddCalculator.averageTDD(tddCalculator.calculate(7)).totalAmount) this.mealData.put("TDDPUMP", tddCalculator.calculateDaily().totalAmount) - this.mealData.put("TDDLast24", tddCalculator!!.calculate24Daily().totalAmount) + this.mealData.put("TDDLast24", tddCalculator.calculate24Daily().totalAmount) if (constraintChecker.isAutosensModeEnabled().value()) { autosensData.put("ratio", autosensDataRatio) diff --git a/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt b/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt index 34663d0800..05b1226c1b 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt @@ -142,7 +142,7 @@ class TddCalculator @Inject constructor( //result.put(midnight, tdd) } val calculationStep = T.mins(5).msecs() - val tempBasals = iobCobCalculator.getTempBasalIncludingConvertedExtendedForRange(startTime, endTime, calculationStep) + //val tempBasals = iobCobCalculator.getTempBasalIncludingConvertedExtendedForRange(startTime, endTime, calculationStep) for (t in startTime until endTime step calculationStep) { //val midnight = MidnightTime.calc(t) diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboFragment.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboFragment.java index 6c760c5297..28cd911379 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboFragment.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboFragment.java @@ -40,6 +40,7 @@ public class ComboFragment extends DaggerFragment { @Inject DateUtil dateUtil; @Inject FabricPrivacy fabricPrivacy; @Inject AapsSchedulers aapsSchedulers; + @Inject ComboErrorUtil errorUtil; private final CompositeDisposable disposable = new CompositeDisposable(); @@ -264,8 +265,6 @@ public class ComboFragment extends DaggerFragment { private void updateErrorDisplay(boolean forceHide) { int errorCount = -1; - ComboErrorUtil errorUtil = ComboErrorUtil.getInstance(); - if (!forceHide) { ComboErrorUtil.DisplayType displayType = errorUtil.getDisplayType(); diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java index 29d38d54f3..197a4f70b6 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java @@ -38,9 +38,6 @@ import info.nightscout.androidaps.interfaces.Pump; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpPluginBase; import info.nightscout.androidaps.interfaces.PumpSync; -import info.nightscout.androidaps.plugins.pump.combo.data.ComboErrorUtil; -import info.nightscout.shared.logging.AAPSLogger; -import info.nightscout.shared.logging.LTag; import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.plugins.common.ManufacturerType; import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; @@ -65,6 +62,8 @@ import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.InstanceId; import info.nightscout.androidaps.utils.T; import info.nightscout.androidaps.utils.resources.ResourceHelper; +import info.nightscout.shared.logging.AAPSLogger; +import info.nightscout.shared.logging.LTag; import info.nightscout.shared.sharedPreferences.SP; /** @@ -99,10 +98,10 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints { private final Context context; private final PumpSync pumpSync; private final DateUtil dateUtil; + private final RuffyCommands ruffyScripter; private final static PumpDescription pumpDescription = new PumpDescription(); - private RuffyCommands ruffyScripter; @NonNull private static final ComboPump pump = new ComboPump(); @@ -154,7 +153,8 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints { CommandQueue commandQueue, Context context, PumpSync pumpSync, - DateUtil dateUtil + DateUtil dateUtil, + RuffyScripter ruffyScripter ) { super(new PluginDescription() .mainType(PluginType.PUMP) @@ -173,16 +173,13 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints { this.context = context; this.pumpSync = pumpSync; this.dateUtil = dateUtil; - - ComboErrorUtil.getInstance().setSP(sp); - ComboErrorUtil.getInstance().clearErrors(); + this.ruffyScripter = ruffyScripter; pumpDescription.fillFor(PumpType.ACCU_CHEK_COMBO); } @Override protected void onStart() { super.onStart(); - ruffyScripter = new RuffyScripter(context); OPERATION_NOT_SUPPORTED = new PumpEnactResult(getInjector()) .success(false).enacted(false).comment(R.string.combo_pump_unsupported_operation); } diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ComboErrorUtil.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ComboErrorUtil.java deleted file mode 100755 index 79ce7b71dc..0000000000 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ComboErrorUtil.java +++ /dev/null @@ -1,106 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.combo.data; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import info.nightscout.androidaps.combo.R; -import info.nightscout.shared.sharedPreferences.SP; - -/** - * Created by andy on 3/17/18. - */ -public class ComboErrorUtil { - - private SP sp; - - Map> errorMap = new HashMap<>(); - - private static final ComboErrorUtil comboDataUtil = new ComboErrorUtil(); - - private ComboErrorUtil() { - } - - public static ComboErrorUtil getInstance() { - return comboDataUtil; - } - - public void setSP(SP sp) { - this.sp = sp; - } - - public void addError(Exception exception) { - String exceptionMsg = exception.getMessage(); - - if (!errorMap.containsKey(exceptionMsg)) { - List list = new ArrayList<>(); - list.add(createErrorState(exception)); - - errorMap.put(exceptionMsg, list); - } else { - errorMap.get(exceptionMsg).add(createErrorState(exception)); - } - - updateErrorCount(); - } - - - private void updateErrorCount() { - int errorCount = 0; - - if (!isErrorPresent()) { - for (List errorStates : errorMap.values()) { - errorCount += errorStates.size(); - } - } - - if (errorCount==0) { - if (sp.contains(R.string.key_combo_error_count)) { - sp.remove(R.string.key_combo_error_count); - } - } else { - sp.putInt(R.string.key_combo_error_count, errorCount); - } - } - - private ErrorState createErrorState(Exception exception) { - ErrorState errorState = new ErrorState(); - errorState.setException(exception); - errorState.setTimeInMillis(System.currentTimeMillis()); - - return errorState; - } - - public void clearErrors() { - if (errorMap != null) - this.errorMap.clear(); - else - this.errorMap = new HashMap<>(); - - if (sp.contains(R.string.key_combo_error_count)) { - sp.remove(R.string.key_combo_error_count); - } - } - - public boolean isErrorPresent() { - return !this.errorMap.isEmpty(); - } - - public int getErrorCount() { - return sp.contains(R.string.key_combo_error_count) ? - sp.getInt(R.string.key_combo_error_count, -1) : -1; - } - - public DisplayType getDisplayType() { - String displayTypeString = sp.getString(R.string.key_show_comm_error_count, "ON_ERROR"); - return DisplayType.valueOf(displayTypeString); - } - - public enum DisplayType { - NEVER, - ON_ERROR, - ALWAYS - } - -} diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ComboErrorUtil.kt b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ComboErrorUtil.kt new file mode 100644 index 0000000000..a1a74f2008 --- /dev/null +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ComboErrorUtil.kt @@ -0,0 +1,49 @@ +package info.nightscout.androidaps.plugins.pump.combo.data + +import info.nightscout.androidaps.combo.R +import info.nightscout.shared.sharedPreferences.SP +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class ComboErrorUtil @Inject constructor( + private val sp: SP +) { + + class ErrorState(val exception: Exception, val timeInMillis: Long) + + enum class DisplayType { + NEVER, ON_ERROR, ALWAYS + } + + private var errorMap: MutableMap> = HashMap() + + fun addError(exception: Exception) { + val exceptionMsg = exception.message ?: return + if (!errorMap.containsKey(exceptionMsg)) errorMap[exceptionMsg] = ArrayList().also { it.add(createErrorState(exception)) } + else errorMap[exceptionMsg]?.add(createErrorState(exception)) + updateErrorCount() + } + + private fun updateErrorCount() { + var errorCount = 0 + if (!isErrorPresent) for (errorStates in errorMap.values) errorCount += errorStates.size + if (errorCount == 0) { + if (sp.contains(R.string.key_combo_error_count)) sp.remove(R.string.key_combo_error_count) + } else sp.putInt(R.string.key_combo_error_count, errorCount) + } + + private fun createErrorState(exception: Exception) = ErrorState(exception, System.currentTimeMillis()) + + fun clearErrors() { + errorMap.clear() + if (sp.contains(R.string.key_combo_error_count)) sp.remove(R.string.key_combo_error_count) + } + + private val isErrorPresent: Boolean + get() = errorMap.isNotEmpty() + val errorCount: Int + get() = if (sp.contains(R.string.key_combo_error_count)) sp.getInt(R.string.key_combo_error_count, -1) else -1 + val displayType: DisplayType + get() = DisplayType.valueOf(sp.getString(R.string.key_show_comm_error_count, "ON_ERROR")) +} \ No newline at end of file diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ErrorState.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ErrorState.java deleted file mode 100755 index ec00441309..0000000000 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/data/ErrorState.java +++ /dev/null @@ -1,17 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.combo.data; - -public class ErrorState { - - private Exception exception; - private long timeInMillis; - - - public void setException(Exception exception) { - this.exception = exception; - } - - - public void setTimeInMillis(long timeInMillis) { - this.timeInMillis = timeInMillis; - } -} diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/RuffyScripter.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/RuffyScripter.java index 155c9f45ae..3aa46ad0f4 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/RuffyScripter.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/RuffyScripter.java @@ -7,6 +7,7 @@ import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -19,16 +20,15 @@ import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; import org.monkey.d.ruffy.ruffy.driver.display.MenuType; import org.monkey.d.ruffy.ruffy.driver.display.menu.BolusType; import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuTime; -import org.slf4j.Logger; import java.util.Date; import java.util.List; import java.util.Objects; +import javax.inject.Inject; +import javax.inject.Singleton; + import info.nightscout.androidaps.plugins.pump.combo.data.ComboErrorUtil; -import info.nightscout.shared.logging.StacktraceLoggerWrapper; -import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands.ReadQuickInfoCommand; -import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.PumpHistoryRequest; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands.BolusCommand; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands.CancelTbrCommand; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands.Command; @@ -37,18 +37,24 @@ import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands.Conf import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands.ReadBasalProfileCommand; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands.ReadHistoryCommand; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands.ReadPumpStateCommand; +import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands.ReadQuickInfoCommand; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands.SetBasalProfileCommand; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands.SetTbrCommand; +import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.PumpHistoryRequest; +import info.nightscout.shared.logging.AAPSLogger; +import info.nightscout.shared.logging.LTag; /** * Provides scripting 'runtime' and operations. consider moving operations into a separate * class and inject that into executing commands, so that commands operately solely on * operations and are cleanly separated from the thread management, connection management etc */ +@Singleton public class RuffyScripter implements RuffyCommands { - private static final Logger log = StacktraceLoggerWrapper.getLogger(RuffyScripter.class); private IRuffyService ruffyService; + private final ComboErrorUtil comboErrorUtil; + private final AAPSLogger aapsLogger; @Nullable private volatile Menu currentMenu; @@ -64,30 +70,28 @@ public class RuffyScripter implements RuffyCommands { private final IRTHandler mHandler = new IRTHandler.Stub() { @Override public void log(String message) { - if (log.isTraceEnabled()) { - log.trace("Ruffy says: " + message); - } + aapsLogger.debug(LTag.PUMP, "Ruffy says: " + message); } @Override public void fail(String message) { - log.warn("Ruffy warns: " + message); + aapsLogger.warn(LTag.PUMP, "Ruffy warns: " + message); } @Override public void requestBluetooth() { - log.trace("Ruffy invoked requestBluetooth callback"); + aapsLogger.debug(LTag.PUMP, "Ruffy invoked requestBluetooth callback"); } @Override public void rtStopped() { - log.debug("rtStopped callback invoked"); + aapsLogger.debug(LTag.PUMP, "rtStopped callback invoked"); currentMenu = null; } @Override public void rtStarted() { - log.debug("rtStarted callback invoked"); + aapsLogger.debug(LTag.PUMP, "rtStarted callback invoked"); } @Override @@ -101,7 +105,7 @@ public class RuffyScripter implements RuffyCommands { @Override public void rtDisplayHandleMenu(Menu menu) { // method is called every ~500ms - log.debug("rtDisplayHandleMenu: " + menu); + aapsLogger.debug(LTag.PUMP, "rtDisplayHandleMenu: " + menu); currentMenu = menu; menuLastUpdated = System.currentTimeMillis(); @@ -113,14 +117,18 @@ public class RuffyScripter implements RuffyCommands { @Override public void rtDisplayHandleNoMenu() { - log.warn("rtDisplayHandleNoMenu callback invoked"); + aapsLogger.warn(LTag.PUMP, "rtDisplayHandleNoMenu callback invoked"); unparsableMenuEncountered = true; } }; - public RuffyScripter(Context context) { + @Inject + public RuffyScripter(Context context, ComboErrorUtil comboErrorUtil, AAPSLogger aapsLogger) { boolean boundSucceeded = false; + this.comboErrorUtil = comboErrorUtil; + this.aapsLogger = aapsLogger; + try { Intent intent = new Intent() .setComponent(new ComponentName( @@ -139,28 +147,28 @@ public class RuffyScripter implements RuffyCommands { ServiceConnection mRuffyServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { - log.debug("ruffy service connected"); + aapsLogger.debug(LTag.PUMP, "ruffy service connected"); ruffyService = IRuffyService.Stub.asInterface(service); try { ruffyService.setHandler(mHandler); } catch (Exception e) { - log.error("Ruffy handler has issues", e); + aapsLogger.error(LTag.PUMP, "Ruffy handler has issues", e); } started = true; } @Override public void onServiceDisconnected(ComponentName name) { - log.debug("ruffy service disconnected"); + aapsLogger.debug(LTag.PUMP, "ruffy service disconnected"); } }; boundSucceeded = context.bindService(intent, mRuffyServiceConnection, Context.BIND_AUTO_CREATE); } catch (Exception e) { - log.error("Binding to ruffy service failed", e); + aapsLogger.error(LTag.PUMP, "Binding to ruffy service failed", e); } if (!boundSucceeded) { - log.info("No connection to ruffy. Pump control unavailable."); + aapsLogger.info(LTag.PUMP, "No connection to ruffy. Pump control unavailable."); } } @@ -191,9 +199,9 @@ public class RuffyScripter implements RuffyCommands { private void addError(Exception e) { try { - ComboErrorUtil.getInstance().addError(e); + comboErrorUtil.addError(e); } catch (Exception ex) { - log.error("Combo data util problem." + ex.getMessage(), ex); + aapsLogger.error(LTag.PUMP, "Combo data util problem." + ex.getMessage(), ex); } } @@ -203,17 +211,17 @@ public class RuffyScripter implements RuffyCommands { return; } try { - log.debug("Disconnecting"); + aapsLogger.debug(LTag.PUMP, "Disconnecting"); ruffyService.doRTDisconnect(); try { - ComboErrorUtil.getInstance().clearErrors(); + comboErrorUtil.clearErrors(); } catch (Exception ex) { - log.error("Combo data util problem." + ex.getMessage(), ex); + aapsLogger.error(LTag.PUMP, "Combo data util problem." + ex.getMessage(), ex); } } catch (RemoteException e) { // ignore } catch (Exception e) { - log.warn("Disconnect not happy", e); + aapsLogger.warn(LTag.PUMP, "Disconnect not happy", e); addError(e); } } @@ -225,14 +233,14 @@ public class RuffyScripter implements RuffyCommands { @Override public CommandResult readQuickInfo(int numberOfBolusRecordsToRetrieve) { - return runCommand(new ReadQuickInfoCommand(numberOfBolusRecordsToRetrieve)); + return runCommand(new ReadQuickInfoCommand(numberOfBolusRecordsToRetrieve, aapsLogger)); } public void returnToRootMenu() { // returning to main menu using the 'back' key does not cause a vibration MenuType menuType = getCurrentMenu().getType(); while (menuType != MenuType.MAIN_MENU && menuType != MenuType.STOP && menuType != MenuType.WARNING_OR_ERROR) { - log.debug("Going back to main menu, currently at " + menuType); + aapsLogger.debug(LTag.PUMP, "Going back to main menu, currently at " + menuType); pressBackKey(); while (getCurrentMenu().getType() == menuType) { waitForScreenUpdate(); @@ -245,11 +253,11 @@ public class RuffyScripter implements RuffyCommands { * Always returns a CommandResult, never throws */ private CommandResult runCommand(final Command cmd) { - log.debug("Attempting to run cmd: " + cmd); + aapsLogger.debug(LTag.PUMP, "Attempting to run cmd: " + cmd); List violations = cmd.validateArguments(); if (!violations.isEmpty()) { - log.error("Command argument violations: " + Joiner.on(", ").join(violations)); + aapsLogger.error(LTag.PUMP, "Command argument violations: " + Joiner.on(", ").join(violations)); return new CommandResult().success(false).state(new PumpState()); } @@ -260,27 +268,27 @@ public class RuffyScripter implements RuffyCommands { unparsableMenuEncountered = false; long connectStart = System.currentTimeMillis(); ensureConnected(); - log.debug("Connection ready to execute cmd " + cmd); + aapsLogger.debug(LTag.PUMP, "Connection ready to execute cmd " + cmd); cmdThread = new Thread(() -> { try { if (!runPreCommandChecks(cmd)) { return; } PumpState pumpState = readPumpStateInternal(); - log.debug("Pump state before running command: " + pumpState); + aapsLogger.debug(LTag.PUMP, "Pump state before running command: " + pumpState); // execute the command cmd.setScripter(RuffyScripter.this); long cmdStartTime = System.currentTimeMillis(); cmd.execute(); long cmdEndTime = System.currentTimeMillis(); - log.debug("Executing " + cmd + " took " + (cmdEndTime - cmdStartTime) + "ms"); + aapsLogger.debug(LTag.PUMP, "Executing " + cmd + " took " + (cmdEndTime - cmdStartTime) + "ms"); } catch (CommandException e) { - log.info("CommandException running command", e); + aapsLogger.info(LTag.PUMP, "CommandException running command", e); addError(e); cmd.getResult().success = false; } catch (Exception e) { - log.error("Unexpected exception running cmd", e); + aapsLogger.error(LTag.PUMP, "Unexpected exception running cmd", e); addError(e); cmd.getResult().success = false; } @@ -294,7 +302,7 @@ public class RuffyScripter implements RuffyCommands { // on connection loss try to reconnect, confirm warning alerts caused by // the disconnected and then return the command as failed (the caller // can retry if needed). - log.debug("Connection unusable (ruffy connection: " + ruffyService.isConnected() + ", " + aapsLogger.debug(LTag.PUMP, "Connection unusable (ruffy connection: " + ruffyService.isConnected() + ", " + "time since last menu update: " + (System.currentTimeMillis() - menuLastUpdated) + " ms, " + "aborting command and attempting reconnect ..."); cmdThread.interrupt(); @@ -317,46 +325,44 @@ public class RuffyScripter implements RuffyCommands { } if (System.currentTimeMillis() > overallTimeout) { - log.error("Command " + cmd + " timed out"); + aapsLogger.error(LTag.PUMP, "Command " + cmd + " timed out"); cmdThread.interrupt(); activeCmd.getResult().success = false; break; } if (unparsableMenuEncountered) { - log.error("UnparsableMenuEncountered flagged, aborting command"); + aapsLogger.error(LTag.PUMP, "UnparsableMenuEncountered flagged, aborting command"); cmdThread.interrupt(); activeCmd.getResult().invalidSetup = true; activeCmd.getResult().success = false; } - log.trace("Waiting for running command to complete"); + aapsLogger.debug(LTag.PUMP, "Waiting for running command to complete"); SystemClock.sleep(500); } activeCmd.getResult().state = readPumpStateInternal(); CommandResult result = activeCmd.getResult(); - if (log.isDebugEnabled()) { - long connectDurationSec = (executionStart - connectStart) / 1000; - long executionDurationSec = (System.currentTimeMillis() - executionStart) / 1000; - log.debug("Command result: " + result); - log.debug("Connect: " + connectDurationSec + "s, execution: " + executionDurationSec + "s"); - } + long connectDurationSec = (executionStart - connectStart) / 1000; + long executionDurationSec = (System.currentTimeMillis() - executionStart) / 1000; + aapsLogger.debug(LTag.PUMP, "Command result: " + result); + aapsLogger.debug(LTag.PUMP, "Connect: " + connectDurationSec + "s, execution: " + executionDurationSec + "s"); return result; } catch (CommandException e) { - log.error("CommandException while executing command", e); + aapsLogger.error(LTag.PUMP, "CommandException while executing command", e); PumpState pumpState = recoverFromCommandFailure(); addError(e); return activeCmd.getResult().success(false).state(pumpState); } catch (Exception e) { - log.error("Unexpected exception communication with ruffy", e); + aapsLogger.error(LTag.PUMP, "Unexpected exception communication with ruffy", e); PumpState pumpState = recoverFromCommandFailure(); addError(e); return activeCmd.getResult().success(false).state(pumpState); } finally { Menu menu = this.currentMenu; if (activeCmd.getResult().success && menu != null && menu.getType() != MenuType.MAIN_MENU) { - log.warn("Command " + activeCmd + " successful, but finished leaving pump on menu " + getCurrentMenuName()); + aapsLogger.warn(LTag.PUMP, "Command " + activeCmd + " successful, but finished leaving pump on menu " + getCurrentMenuName()); } if (cmdThread != null) { try { @@ -377,18 +383,18 @@ public class RuffyScripter implements RuffyCommands { activeCmd.getResult().success = true; } else if (getCurrentMenu().getType() == MenuType.STOP) { if (cmd.needsRunMode()) { - log.error("Requested command requires run mode, but pump is suspended"); + aapsLogger.error(LTag.PUMP, "Requested command requires run mode, but pump is suspended"); activeCmd.getResult().success = false; return false; } } else if (getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) { if (!(cmd instanceof ConfirmAlertCommand)) { - log.warn("Warning/alert active on pump, but requested command is not ConfirmAlertCommand"); + aapsLogger.warn(LTag.PUMP, "Warning/alert active on pump, but requested command is not ConfirmAlertCommand"); activeCmd.getResult().success = false; return false; } } else if (getCurrentMenu().getType() != MenuType.MAIN_MENU) { - log.debug("Pump is unexpectedly not on main menu but " + getCurrentMenuName() + ", trying to recover"); + aapsLogger.debug(LTag.PUMP, "Pump is unexpectedly not on main menu but " + getCurrentMenuName() + ", trying to recover"); try { recoverFromCommandFailure(); } catch (Exception e) { @@ -411,12 +417,12 @@ public class RuffyScripter implements RuffyCommands { * @return whether the reconnect and return to main menu was successful */ private boolean recoverFromConnectionLoss() { - log.debug("Connection was lost, trying to reconnect"); + aapsLogger.debug(LTag.PUMP, "Connection was lost, trying to reconnect"); ensureConnected(); if (getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) { WarningOrErrorCode warningOrErrorCode = readWarningOrErrorCode(); if (Objects.equals(activeCmd.getReconnectWarningId(), warningOrErrorCode.warningCode)) { - log.debug("Confirming warning caused by disconnect: #" + warningOrErrorCode.warningCode); + aapsLogger.debug(LTag.PUMP, "Confirming warning caused by disconnect: #" + warningOrErrorCode.warningCode); // confirm alert verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR); pressCheckKey(); @@ -433,7 +439,7 @@ public class RuffyScripter implements RuffyCommands { returnToRootMenu(); } } - log.debug("Recovery from connection loss " + (connected ? "succeeded" : "failed")); + aapsLogger.debug(LTag.PUMP, "Recovery from connection loss " + (connected ? "succeeded" : "failed")); return connected; } @@ -449,17 +455,16 @@ public class RuffyScripter implements RuffyCommands { MenuType type = menu.getType(); if (type != MenuType.WARNING_OR_ERROR && type != MenuType.MAIN_MENU) { try { - log.debug("Command execution yielded an error, returning to main menu"); + aapsLogger.debug(LTag.PUMP, "Command execution yielded an error, returning to main menu"); returnToRootMenu(); } catch (Exception e) { - log.warn("Error returning to main menu, when trying to recover from command failure", e); + aapsLogger.warn(LTag.PUMP, "Error returning to main menu, when trying to recover from command failure", e); } } try { - PumpState pumpState = readPumpStateInternal(); - return pumpState; + return readPumpStateInternal(); } catch (Exception e) { - log.debug("Reading pump state during recovery failed", e); + aapsLogger.debug(LTag.PUMP, "Reading pump state during recovery failed", e); return new PumpState(); } } @@ -474,8 +479,8 @@ public class RuffyScripter implements RuffyCommands { } boolean connectInitSuccessful = ruffyService.doRTConnect() == 0; - log.debug("Connect init successful: " + connectInitSuccessful); - log.debug("Waiting for first menu update to be sent"); + aapsLogger.debug(LTag.PUMP, "Connect init successful: " + connectInitSuccessful); + aapsLogger.debug(LTag.PUMP, "Waiting for first menu update to be sent"); long timeoutExpired = System.currentTimeMillis() + 90 * 1000; long initialUpdateTime = menuLastUpdated; while (initialUpdateTime == menuLastUpdated) { @@ -488,14 +493,14 @@ public class RuffyScripter implements RuffyCommands { try { ruffyService.doRTDisconnect(); } catch (RemoteException e1) { - log.warn("Disconnect after connect failure failed", e1); + aapsLogger.warn(LTag.PUMP, "Disconnect after connect failure failed", e1); } throw e; } catch (Exception e) { try { ruffyService.doRTDisconnect(); } catch (RemoteException e1) { - log.warn("Disconnect after connect failure failed", e1); + aapsLogger.warn(LTag.PUMP, "Disconnect after connect failure failed", e1); } throw new CommandException("Unexpected exception while initiating/restoring pump connection", e); } @@ -510,11 +515,11 @@ public class RuffyScripter implements RuffyCommands { state.timestamp = System.currentTimeMillis(); Menu menu = currentMenu; if (menu == null) { - log.debug("Returning empty PumpState, menu is unavailable"); + aapsLogger.debug(LTag.PUMP, "Returning empty PumpState, menu is unavailable"); return state; } - log.debug("Parsing menu: " + menu); + aapsLogger.debug(LTag.PUMP, "Parsing menu: " + menu); MenuType menuType = menu.getType(); state.menu = menuType.name(); @@ -577,7 +582,7 @@ public class RuffyScripter implements RuffyCommands { } } - log.debug("State read: " + state); + aapsLogger.debug(LTag.PUMP, "State read: " + state); return state; } @@ -615,7 +620,7 @@ public class RuffyScripter implements RuffyCommands { throw new CommandException("Interrupted"); Menu menu = this.currentMenu; if (menu == null) { - log.error("currentMenu == null, bailing"); + aapsLogger.error(LTag.PUMP, "currentMenu == null, bailing"); throw new CommandException("Unable to read current menu"); } return menu; @@ -628,39 +633,39 @@ public class RuffyScripter implements RuffyCommands { } public void pressUpKey() { - log.debug("Pressing up key"); + aapsLogger.debug(LTag.PUMP, "Pressing up key"); pressKey(Key.UP); - log.debug("Releasing up key"); + aapsLogger.debug(LTag.PUMP, "Releasing up key"); } public void pressDownKey() { - log.debug("Pressing down key"); + aapsLogger.debug(LTag.PUMP, "Pressing down key"); pressKey(Key.DOWN); - log.debug("Releasing down key"); + aapsLogger.debug(LTag.PUMP, "Releasing down key"); } public void pressCheckKey() { - log.debug("Pressing check key"); + aapsLogger.debug(LTag.PUMP, "Pressing check key"); pressKey(Key.CHECK); - log.debug("Releasing check key"); + aapsLogger.debug(LTag.PUMP, "Releasing check key"); } public void pressMenuKey() { - log.debug("Pressing menu key"); + aapsLogger.debug(LTag.PUMP, "Pressing menu key"); pressKey(Key.MENU); - log.debug("Releasing menu key"); + aapsLogger.debug(LTag.PUMP, "Releasing menu key"); } private void pressBackKey() { - log.debug("Pressing back key"); + aapsLogger.debug(LTag.PUMP, "Pressing back key"); pressKey(Key.BACK); - log.debug("Releasing back key"); + aapsLogger.debug(LTag.PUMP, "Releasing back key"); } public void pressKeyMs(final byte key, long ms) { long stepMs = 100; try { - log.debug("Scroll: Pressing key for " + ms + " ms with step " + stepMs + " ms"); + aapsLogger.debug(LTag.PUMP, "Scroll: Pressing key for " + ms + " ms with step " + stepMs + " ms"); ruffyService.rtSendKey(key, true); ruffyService.rtSendKey(key, false); while (ms > stepMs) { @@ -670,7 +675,7 @@ public class RuffyScripter implements RuffyCommands { } SystemClock.sleep(ms); ruffyService.rtSendKey(Key.NO_KEY, true); - log.debug("Releasing key"); + aapsLogger.debug(LTag.PUMP, "Releasing key"); } catch (Exception e) { throw new CommandException("Error while pressing buttons"); } @@ -709,7 +714,7 @@ public class RuffyScripter implements RuffyCommands { int moves = 20; MenuType lastSeenMenu = getCurrentMenu().getType(); while (lastSeenMenu != desiredMenu) { - log.debug("Navigating to menu " + desiredMenu + ", current menu: " + lastSeenMenu); + aapsLogger.debug(LTag.PUMP, "Navigating to menu " + desiredMenu + ", current menu: " + lastSeenMenu); moves--; if (moves == 0) { throw new CommandException("Menu not found searching for " + desiredMenu @@ -788,7 +793,7 @@ public class RuffyScripter implements RuffyCommands { @Override public CommandResult deliverBolus(double amount, BolusProgressReporter bolusProgressReporter) { - return runCommand(new BolusCommand(amount, bolusProgressReporter)); + return runCommand(new BolusCommand(amount, bolusProgressReporter, aapsLogger)); } @Override @@ -796,18 +801,18 @@ public class RuffyScripter implements RuffyCommands { if (activeCmd instanceof BolusCommand) { ((BolusCommand) activeCmd).requestCancellation(); } else { - log.error("cancelBolus called, but active command is not a bolus:" + activeCmd); + aapsLogger.error(LTag.PUMP, "cancelBolus called, but active command is not a bolus:" + activeCmd); } } @Override public CommandResult setTbr(int percent, int duration) { - return runCommand(new SetTbrCommand(percent, duration)); + return runCommand(new SetTbrCommand(percent, duration, aapsLogger)); } @Override public CommandResult cancelTbr() { - return runCommand(new CancelTbrCommand()); + return runCommand(new CancelTbrCommand(aapsLogger)); } @Override @@ -817,17 +822,17 @@ public class RuffyScripter implements RuffyCommands { @Override public CommandResult readHistory(PumpHistoryRequest request) { - return runCommand(new ReadHistoryCommand(request)); + return runCommand(new ReadHistoryCommand(request, aapsLogger)); } @Override public CommandResult readBasalProfile() { - return runCommand(new ReadBasalProfileCommand()); + return runCommand(new ReadBasalProfileCommand(aapsLogger)); } @Override public CommandResult setBasalProfile(BasalProfile basalProfile) { - return runCommand(new SetBasalProfileCommand(basalProfile)); + return runCommand(new SetBasalProfileCommand(basalProfile, aapsLogger)); } @Override @@ -887,8 +892,8 @@ public class RuffyScripter implements RuffyCommands { // when a command returns WarningOrErrorCode displayedWarning = readWarningOrErrorCode(); while (Objects.equals(displayedWarning.warningCode, warningCode)) { - waitForScreenUpdate(); - displayedWarning = readWarningOrErrorCode(); + waitForScreenUpdate(); + displayedWarning = readWarningOrErrorCode(); } return true; } diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/BolusCommand.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/BolusCommand.java index 3b9f7a26d6..1e0105f094 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/BolusCommand.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/BolusCommand.java @@ -1,39 +1,41 @@ package info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands; -import android.os.SystemClock; - -import androidx.annotation.NonNull; - -import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; -import org.monkey.d.ruffy.ruffy.driver.display.MenuType; -import org.slf4j.Logger; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import info.nightscout.shared.logging.StacktraceLoggerWrapper; -import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.BolusProgressReporter; -import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.PumpWarningCodes; -import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.RuffyScripter; -import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.WarningOrErrorCode; - import static info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.BolusProgressReporter.State.DELIVERED; import static info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.BolusProgressReporter.State.DELIVERING; import static info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.BolusProgressReporter.State.PROGRAMMING; import static info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.BolusProgressReporter.State.STOPPED; import static info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.BolusProgressReporter.State.STOPPING; +import android.os.SystemClock; + +import androidx.annotation.NonNull; + +import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; +import org.monkey.d.ruffy.ruffy.driver.display.MenuType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.BolusProgressReporter; +import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.PumpWarningCodes; +import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.RuffyScripter; +import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.WarningOrErrorCode; +import info.nightscout.shared.logging.AAPSLogger; +import info.nightscout.shared.logging.LTag; + public class BolusCommand extends BaseCommand { - private static final Logger log = StacktraceLoggerWrapper.getLogger(BolusCommand.class); + + private final AAPSLogger aapsLogger; protected final double bolus; private final BolusProgressReporter bolusProgressReporter; private volatile boolean cancelRequested; - public BolusCommand(double bolus, BolusProgressReporter bolusProgressReporter) { + public BolusCommand(double bolus, BolusProgressReporter bolusProgressReporter, AAPSLogger aapsLogger) { this.bolus = bolus; this.bolusProgressReporter = bolusProgressReporter; + this.aapsLogger = aapsLogger; } @Override @@ -57,7 +59,7 @@ public class BolusCommand extends BaseCommand { if (cancelRequested) { bolusProgressReporter.report(STOPPED, 0, 0); result.success = true; - log.debug("Stage 0: cancelled bolus before programming"); + aapsLogger.debug(LTag.PUMP, "Stage 0: cancelled bolus before programming"); return; } @@ -72,26 +74,26 @@ public class BolusCommand extends BaseCommand { scripter.returnToRootMenu(); bolusProgressReporter.report(STOPPED, 0, 0); result.success = true; - log.debug("Stage 1: cancelled bolus after programming"); + aapsLogger.debug(LTag.PUMP, "Stage 1: cancelled bolus after programming"); return; } // confirm bolus scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); scripter.pressCheckKey(); - log.debug("Stage 2: bolus confirmed"); + aapsLogger.debug(LTag.PUMP, "Stage 2: bolus confirmed"); // the pump displays the entered bolus and waits a few seconds to let user check and cancel while (scripter.getCurrentMenu().getType() == MenuType.BOLUS_ENTER) { if (cancelRequested) { - log.debug("Stage 2: cancelling during confirmation wait"); + aapsLogger.debug(LTag.PUMP, "Stage 2: cancelling during confirmation wait"); bolusProgressReporter.report(STOPPING, 0, 0); scripter.pressUpKey(); // wait up to 1s for a BOLUS_CANCELLED alert, if it doesn't happen we missed // the window, simply continue and let the next cancel attempt try its luck boolean alertWasCancelled = scripter.confirmAlert(PumpWarningCodes.BOLUS_CANCELLED, 1000); if (alertWasCancelled) { - log.debug("Stage 2: successfully cancelled during confirmation wait"); + aapsLogger.debug(LTag.PUMP, "Stage 2: successfully cancelled during confirmation wait"); bolusProgressReporter.report(STOPPED, 0, 0); result.success = true; return; @@ -113,7 +115,7 @@ public class BolusCommand extends BaseCommand { Thread cancellationThread = null; while (bolusRemaining != null || scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) { if (cancelRequested && !cancelInProgress) { - log.debug("Stage 3: cancellation while delivering bolus"); + aapsLogger.debug(LTag.PUMP, "Stage 3: cancellation while delivering bolus"); bolusProgressReporter.report(STOPPING, 0, 0); cancelInProgress = true; cancellationThread = new Thread(() -> @@ -139,15 +141,15 @@ public class BolusCommand extends BaseCommand { } scripter.confirmAlert(PumpWarningCodes.BOLUS_CANCELLED, 2000); bolusProgressReporter.report(STOPPED, 0, 0); - log.debug("Stage 3: confirmed BOLUS CANCELLED after cancelling bolus during delivery"); + aapsLogger.debug(LTag.PUMP, "Stage 3: confirmed BOLUS CANCELLED after cancelling bolus during delivery"); } else if (Objects.equals(warningCode, PumpWarningCodes.CARTRIDGE_LOW)) { scripter.confirmAlert(PumpWarningCodes.CARTRIDGE_LOW, 2000); result.forwardedWarnings.add(PumpWarningCodes.CARTRIDGE_LOW); - log.debug("Stage 3: confirmed low cartridge alert and forwarding to AAPS"); + aapsLogger.debug(LTag.PUMP, "Stage 3: confirmed low cartridge alert and forwarding to AAPS"); } else if (Objects.equals(warningCode, PumpWarningCodes.BATTERY_LOW)) { scripter.confirmAlert(PumpWarningCodes.BATTERY_LOW, 2000); result.forwardedWarnings.add(PumpWarningCodes.BATTERY_LOW); - log.debug("Stage 3: confirmed low battery alert and forwarding to AAPS"); + aapsLogger.debug(LTag.PUMP, "Stage 3: confirmed low battery alert and forwarding to AAPS"); } else { // all other warnings or errors; // An occlusion error can also occur during bolus. To read the partially delivered @@ -165,7 +167,7 @@ public class BolusCommand extends BaseCommand { } } if (bolusRemaining != null && !Objects.equals(bolusRemaining, lastBolusReported)) { - log.debug("Delivering bolus, remaining: " + bolusRemaining); + aapsLogger.debug(LTag.PUMP, "Delivering bolus, remaining: " + bolusRemaining); int percentDelivered = (int) (100 - (bolusRemaining / bolus * 100)); bolusProgressReporter.report(DELIVERING, percentDelivered, bolus - bolusRemaining); lastBolusReported = bolusRemaining; @@ -185,9 +187,9 @@ public class BolusCommand extends BaseCommand { } if (cancelInProgress) { - log.debug("Stage 4: bolus was cancelled, with unknown amount delivered"); + aapsLogger.debug(LTag.PUMP, "Stage 4: bolus was cancelled, with unknown amount delivered"); } else { - log.debug("Stage 4: full bolus of " + bolus + " U was successfully delivered"); + aapsLogger.debug(LTag.PUMP, "Stage 4: full bolus of " + bolus + " U was successfully delivered"); bolusProgressReporter.report(DELIVERED, 100, bolus); } result.success = true; @@ -219,12 +221,12 @@ public class BolusCommand extends BaseCommand { double displayedBolus = scripter.readBlinkingValue(Double.class, MenuAttribute.BOLUS); long timeout = System.currentTimeMillis() + 10 * 1000; while (timeout > System.currentTimeMillis() && bolus - displayedBolus > 0.05) { - log.debug("Waiting for pump to process scrolling input for amount, current: " + displayedBolus + ", desired: " + bolus); + aapsLogger.debug(LTag.PUMP, "Waiting for pump to process scrolling input for amount, current: " + displayedBolus + ", desired: " + bolus); SystemClock.sleep(50); displayedBolus = scripter.readBlinkingValue(Double.class, MenuAttribute.BOLUS); } - log.debug("Final bolus: " + displayedBolus); + aapsLogger.debug(LTag.PUMP, "Final bolus: " + displayedBolus); if (Math.abs(displayedBolus - bolus) > 0.01) { throw new CommandException("Failed to set correct bolus. Expected: " + bolus + ", actual: " + displayedBolus); } @@ -240,7 +242,7 @@ public class BolusCommand extends BaseCommand { } public void requestCancellation() { - log.debug("Bolus cancellation requested"); + aapsLogger.debug(LTag.PUMP, "Bolus cancellation requested"); cancelRequested = true; bolusProgressReporter.report(STOPPING, 0, 0); } diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/CancelTbrCommand.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/CancelTbrCommand.java index d371228070..02b23f971a 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/CancelTbrCommand.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/CancelTbrCommand.java @@ -3,15 +3,19 @@ package info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands; import androidx.annotation.NonNull; import org.monkey.d.ruffy.ruffy.driver.display.MenuType; -import org.slf4j.Logger; -import info.nightscout.shared.logging.StacktraceLoggerWrapper; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.PumpState; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.PumpWarningCodes; +import info.nightscout.shared.logging.AAPSLogger; +import info.nightscout.shared.logging.LTag; public class CancelTbrCommand extends BaseCommand { - private static final Logger log = StacktraceLoggerWrapper.getLogger(CancelTbrCommand.class); + private final AAPSLogger aapsLogger; + public CancelTbrCommand(AAPSLogger aapsLogger) { + this.aapsLogger = aapsLogger; + } + @Override public Integer getReconnectWarningId() { return PumpWarningCodes.TBR_CANCELLED; @@ -28,9 +32,9 @@ public class CancelTbrCommand extends BaseCommand { return; } - log.debug("Cancelling active TBR of " + pumpState.tbrPercent + aapsLogger.debug(LTag.PUMP, "Cancelling active TBR of " + pumpState.tbrPercent + "% with " + pumpState.tbrRemainingDuration + " min remaining"); - SetTbrCommand setTbrCommand = new SetTbrCommand(100, 0); + SetTbrCommand setTbrCommand = new SetTbrCommand(100, 0, aapsLogger); setTbrCommand.setScripter(scripter); setTbrCommand.execute(); result = setTbrCommand.result; diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadBasalProfileCommand.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadBasalProfileCommand.java index 5ef8472a27..09d528099d 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadBasalProfileCommand.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadBasalProfileCommand.java @@ -1,19 +1,25 @@ package info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands; +import androidx.annotation.NonNull; + import org.monkey.d.ruffy.ruffy.driver.display.Menu; import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; import org.monkey.d.ruffy.ruffy.driver.display.MenuType; import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuTime; -import org.slf4j.Logger; import java.util.Arrays; -import info.nightscout.shared.logging.StacktraceLoggerWrapper; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.BasalProfile; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.PumpState; +import info.nightscout.shared.logging.AAPSLogger; +import info.nightscout.shared.logging.LTag; public class ReadBasalProfileCommand extends BaseCommand { - private static final Logger log = StacktraceLoggerWrapper.getLogger(ReadBasalProfileCommand.class); + private final AAPSLogger aapsLogger; + + public ReadBasalProfileCommand(AAPSLogger aapsLogger) { + this.aapsLogger = aapsLogger; + } @Override public void execute() { @@ -44,10 +50,10 @@ public class ReadBasalProfileCommand extends BaseCommand { throw new CommandException("Attempting to read basal rate for hour " + i + ", but hour " + startTime.getHour() + " is displayed"); } basalProfile.hourlyRates[i] = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE); - log.debug("Read basal profile, hour " + i + ": " + basalProfile.hourlyRates[i]); + aapsLogger.debug(LTag.PUMP, "Read basal profile, hour " + i + ": " + basalProfile.hourlyRates[i]); } - log.debug("Basal profile read: " + Arrays.toString(basalProfile.hourlyRates)); + aapsLogger.debug(LTag.PUMP, "Basal profile read: " + Arrays.toString(basalProfile.hourlyRates)); scripter.returnToRootMenu(); scripter.verifyRootMenuIsDisplayed(); @@ -55,7 +61,7 @@ public class ReadBasalProfileCommand extends BaseCommand { result.success(true).basalProfile(basalProfile); } - @Override + @NonNull @Override public String toString() { return "ReadBasalProfileCommand{}"; } diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadHistoryCommand.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadHistoryCommand.java index 63bf471292..d3f03ac6a2 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadHistoryCommand.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadHistoryCommand.java @@ -6,27 +6,27 @@ import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; import org.monkey.d.ruffy.ruffy.driver.display.MenuType; import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuDate; import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuTime; -import org.slf4j.Logger; import java.util.Calendar; import java.util.Date; -import info.nightscout.shared.logging.StacktraceLoggerWrapper; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.Bolus; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.PumpAlert; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.PumpHistory; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.PumpHistoryRequest; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.Tbr; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.Tdd; +import info.nightscout.shared.logging.AAPSLogger; +import info.nightscout.shared.logging.LTag; public class ReadHistoryCommand extends BaseCommand { - private static final Logger log = StacktraceLoggerWrapper.getLogger(ReadHistoryCommand.class); - + private final AAPSLogger aapsLogger; private final PumpHistoryRequest request; private final PumpHistory history = new PumpHistory(); - public ReadHistoryCommand(PumpHistoryRequest request) { + public ReadHistoryCommand(PumpHistoryRequest request, AAPSLogger aapsLogger) { this.request = request; + this.aapsLogger = aapsLogger; } @Override @@ -106,30 +106,28 @@ public class ReadHistoryCommand extends BaseCommand { } } - if (log.isDebugEnabled()) { - if (!history.bolusHistory.isEmpty()) { - log.debug("Read bolus history (" + history.bolusHistory.size() + "):"); - for (Bolus bolus : history.bolusHistory) { - log.debug(new Date(bolus.timestamp) + ": " + bolus.toString()); - } + if (!history.bolusHistory.isEmpty()) { + aapsLogger.debug(LTag.PUMP, "Read bolus history (" + history.bolusHistory.size() + "):"); + for (Bolus bolus : history.bolusHistory) { + aapsLogger.debug(LTag.PUMP, new Date(bolus.timestamp) + ": " + bolus.toString()); } - if (!history.pumpAlertHistory.isEmpty()) { - log.debug("Read error history (" + history.pumpAlertHistory.size() + "):"); - for (PumpAlert pumpAlert : history.pumpAlertHistory) { - log.debug(new Date(pumpAlert.timestamp) + ": " + pumpAlert.toString()); - } + } + if (!history.pumpAlertHistory.isEmpty()) { + aapsLogger.debug(LTag.PUMP, "Read error history (" + history.pumpAlertHistory.size() + "):"); + for (PumpAlert pumpAlert : history.pumpAlertHistory) { + aapsLogger.debug(LTag.PUMP, new Date(pumpAlert.timestamp) + ": " + pumpAlert.toString()); } - if (!history.tddHistory.isEmpty()) { - log.debug("Read TDD history (" + history.tddHistory.size() + "):"); - for (Tdd tdd : history.tddHistory) { - log.debug(new Date(tdd.timestamp) + ": " + tdd.toString()); - } + } + if (!history.tddHistory.isEmpty()) { + aapsLogger.debug(LTag.PUMP, "Read TDD history (" + history.tddHistory.size() + "):"); + for (Tdd tdd : history.tddHistory) { + aapsLogger.debug(LTag.PUMP, new Date(tdd.timestamp) + ": " + tdd.toString()); } - if (!history.tbrHistory.isEmpty()) { - log.debug("Read TBR history (" + history.tbrHistory.size() + "):"); - for (Tbr tbr : history.tbrHistory) { - log.debug(new Date(tbr.timestamp) + ": " + tbr.toString()); - } + } + if (!history.tbrHistory.isEmpty()) { + aapsLogger.debug(LTag.PUMP, "Read TBR history (" + history.tbrHistory.size() + "):"); + for (Tbr tbr : history.tbrHistory) { + aapsLogger.debug(LTag.PUMP, new Date(tbr.timestamp) + ": " + tbr.toString()); } } @@ -147,9 +145,9 @@ public class ReadHistoryCommand extends BaseCommand { if (requestedTime != PumpHistoryRequest.FULL && tdd.timestamp < requestedTime) { break; } - log.debug("Read TDD record #" + record + "/" + totalRecords); + aapsLogger.debug(LTag.PUMP, "Read TDD record #" + record + "/" + totalRecords); history.tddHistory.add(tdd); - log.debug("Parsed " + scripter.getCurrentMenu().toString() + " => " + tdd); + aapsLogger.debug(LTag.PUMP, "Parsed " + scripter.getCurrentMenu() + " => " + tdd); if (record == totalRecords) { break; } @@ -174,7 +172,7 @@ public class ReadHistoryCommand extends BaseCommand { Calendar calendar = Calendar.getInstance(); calendar.set(year, date.getMonth() - 1, date.getDay(), 0, 0, 0); long time = calendar.getTimeInMillis(); - time = time - time%1000; + time = time - time % 1000; return new Tdd(time, dailyTotal); } @@ -186,9 +184,9 @@ public class ReadHistoryCommand extends BaseCommand { if (requestedTime != PumpHistoryRequest.FULL && tbr.timestamp < requestedTime) { break; } - log.debug("Read TBR record #" + record + "/" + totalRecords); + aapsLogger.debug(LTag.PUMP, "Read TBR record #" + record + "/" + totalRecords); history.tbrHistory.add(tbr); - log.debug("Parsed " + scripter.getCurrentMenu().toString() + " => " + tbr); + aapsLogger.debug(LTag.PUMP, "Parsed " + scripter.getCurrentMenu() + " => " + tbr); if (record == totalRecords) { break; } @@ -206,7 +204,7 @@ public class ReadHistoryCommand extends BaseCommand { Double percentage = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.TBR); MenuTime durationTime = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.RUNTIME); int duration = durationTime.getHour() * 60 + durationTime.getMinute(); - long tbrStartDate = readRecordDate() - duration * 60 * 1000; + long tbrStartDate = readRecordDate() - duration * 60L * 1000; return new Tbr(tbrStartDate, duration, percentage.intValue()); } @@ -218,9 +216,9 @@ public class ReadHistoryCommand extends BaseCommand { if (requestedTime != PumpHistoryRequest.FULL && bolus.timestamp < requestedTime) { break; } - log.debug("Read bolus record #" + record + "/" + totalRecords); + aapsLogger.debug(LTag.PUMP, "Read bolus record #" + record + "/" + totalRecords); history.bolusHistory.add(bolus); - log.debug("Parsed " + scripter.getCurrentMenu().toString() + " => " + bolus); + aapsLogger.debug(LTag.PUMP, "Parsed " + scripter.getCurrentMenu() + " => " + bolus); if (record == totalRecords) { break; } @@ -240,9 +238,9 @@ public class ReadHistoryCommand extends BaseCommand { if (requestedTime != PumpHistoryRequest.FULL && error.timestamp < requestedTime) { break; } - log.debug("Read alert record #" + record + "/" + totalRecords); + aapsLogger.debug(LTag.PUMP, "Read alert record #" + record + "/" + totalRecords); history.pumpAlertHistory.add(error); - log.debug("Parsed " + scripter.getCurrentMenu().toString() + " => " + error); + aapsLogger.debug(LTag.PUMP, "Parsed " + scripter.getCurrentMenu() + " => " + error); if (record == totalRecords) { break; } @@ -265,7 +263,7 @@ public class ReadHistoryCommand extends BaseCommand { return new PumpAlert(recordDate, warningCode, errorCode, message); } - @Override + @NonNull @Override public String toString() { return "ReadHistoryCommand{" + "request=" + request + diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadQuickInfoCommand.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadQuickInfoCommand.java index c84a26ee11..f3b19be8bc 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadQuickInfoCommand.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/ReadQuickInfoCommand.java @@ -1,24 +1,27 @@ package info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands; +import androidx.annotation.NonNull; + import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; import org.monkey.d.ruffy.ruffy.driver.display.MenuType; -import org.slf4j.Logger; import java.util.ArrayList; import java.util.Date; import java.util.List; -import info.nightscout.shared.logging.StacktraceLoggerWrapper; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.Bolus; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.PumpHistory; +import info.nightscout.shared.logging.AAPSLogger; +import info.nightscout.shared.logging.LTag; public class ReadQuickInfoCommand extends BaseCommand { - private static final Logger log = StacktraceLoggerWrapper.getLogger(ReadQuickInfoCommand.class); + private final AAPSLogger aapsLogger; private final int numberOfBolusRecordsToRetrieve; - public ReadQuickInfoCommand(int numberOfBolusRecordsToRetrieve) { + public ReadQuickInfoCommand(int numberOfBolusRecordsToRetrieve, AAPSLogger aapsLogger) { this.numberOfBolusRecordsToRetrieve = numberOfBolusRecordsToRetrieve; + this.aapsLogger = aapsLogger; } @Override @@ -53,12 +56,10 @@ public class ReadQuickInfoCommand extends BaseCommand { record = (int) scripter.getCurrentMenu().getAttribute(MenuAttribute.CURRENT_RECORD); } } - if (log.isDebugEnabled()) { - if (!result.history.bolusHistory.isEmpty()) { - log.debug("Read bolus history (" + result.history.bolusHistory.size() + "):"); - for (Bolus bolus : result.history.bolusHistory) { - log.debug(new Date(bolus.timestamp) + ": " + bolus.toString()); - } + if (!result.history.bolusHistory.isEmpty()) { + aapsLogger.debug(LTag.PUMP, "Read bolus history (" + result.history.bolusHistory.size() + "):"); + for (Bolus bolus : result.history.bolusHistory) { + aapsLogger.debug(LTag.PUMP, new Date(bolus.timestamp) + ": " + bolus); } } } @@ -71,7 +72,7 @@ public class ReadQuickInfoCommand extends BaseCommand { return false; } - @Override + @NonNull @Override public String toString() { return "ReadQuickInfoCommand{}"; } diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/SetBasalProfileCommand.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/SetBasalProfileCommand.java index cfb7350a50..343c694ced 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/SetBasalProfileCommand.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/SetBasalProfileCommand.java @@ -2,26 +2,29 @@ package info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands; import android.os.SystemClock; +import androidx.annotation.NonNull; + import org.monkey.d.ruffy.ruffy.driver.display.Menu; import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; import org.monkey.d.ruffy.ruffy.driver.display.MenuType; import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuTime; -import org.slf4j.Logger; import java.util.ArrayList; import java.util.List; -import info.nightscout.shared.logging.StacktraceLoggerWrapper; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.BasalProfile; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.PumpState; +import info.nightscout.shared.logging.AAPSLogger; +import info.nightscout.shared.logging.LTag; public class SetBasalProfileCommand extends BaseCommand { - private static final Logger log = StacktraceLoggerWrapper.getLogger(SetBasalProfileCommand.class); + private final AAPSLogger aapsLogger; private final BasalProfile basalProfile; - public SetBasalProfileCommand(BasalProfile basalProfile) { + public SetBasalProfileCommand(BasalProfile basalProfile, AAPSLogger aapsLogger) { this.basalProfile = basalProfile; + this.aapsLogger = aapsLogger; } @Override @@ -52,7 +55,7 @@ public class SetBasalProfileCommand extends BaseCommand { verifyDisplayedRate(requestedRate, change); } - log.debug("Set basal profile, hour " + i + ": " + requestedRate); + aapsLogger.debug(LTag.PUMP, "Set basal profile, hour " + i + ": " + requestedRate); } // move from hourly values to basal total @@ -78,9 +81,9 @@ public class SetBasalProfileCommand extends BaseCommand { private long inputBasalRate(double requestedRate) { double currentRate = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE); - log.debug("Current rate: " + currentRate + ", requested: " + requestedRate); + aapsLogger.debug(LTag.PUMP, "Current rate: " + currentRate + ", requested: " + requestedRate); // the pump changes steps size from 0.01 to 0.05 when crossing 1.00 U - long steps = 0; + long steps; if (currentRate == 0) { // edge case of starting from 0.00; steps = stepsToOne(0.05) - stepsToOne(requestedRate) + 1; @@ -90,10 +93,10 @@ public class SetBasalProfileCommand extends BaseCommand { if (steps == 0) { return 0; } - log.debug("Pressing " + (steps > 0 ? "up" : "down") + " " + Math.abs(steps) + " times"); + aapsLogger.debug(LTag.PUMP, "Pressing " + (steps > 0 ? "up" : "down") + " " + Math.abs(steps) + " times"); for (int i = 0; i < Math.abs(steps); i++) { scripter.verifyMenuIsDisplayed(MenuType.BASAL_SET); - log.debug("Push #" + (i + 1) + "/" + Math.abs(steps)); + aapsLogger.debug(LTag.PUMP, "Push #" + (i + 1) + "/" + Math.abs(steps)); if (steps > 0) scripter.pressUpKey(); else scripter.pressDownKey(); SystemClock.sleep(50); @@ -119,13 +122,13 @@ public class SetBasalProfileCommand extends BaseCommand { while (timeout > System.currentTimeMillis() && ((change > 0 && requestedRate - displayedRate > 0.001) // displayedRate < requestedRate) || (change < 0 && displayedRate - requestedRate > 0.001))) { //displayedRate > requestedRate))) { - log.debug("Waiting for pump to process scrolling input for rate, current: " + aapsLogger.debug(LTag.PUMP, "Waiting for pump to process scrolling input for rate, current: " + displayedRate + ", desired: " + requestedRate + ", scrolling " + (change > 0 ? "up" : "down")); scripter.waitForScreenUpdate(); displayedRate = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE); } - log.debug("Final displayed basal rate: " + displayedRate); + aapsLogger.debug(LTag.PUMP, "Final displayed basal rate: " + displayedRate); if (Math.abs(displayedRate - requestedRate) > 0.001) { throw new CommandException("Failed to set basal rate, requested: " + requestedRate + ", actual: " + displayedRate); @@ -153,7 +156,7 @@ public class SetBasalProfileCommand extends BaseCommand { return violations; } - @Override + @NonNull @Override public String toString() { return "SetBasalProfileCommand{" + "basalProfile=" + basalProfile + diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/SetTbrCommand.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/SetTbrCommand.java index e08dce0aa1..367367497d 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/SetTbrCommand.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ruffyscripter/commands/SetTbrCommand.java @@ -2,29 +2,32 @@ package info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.commands; import android.os.SystemClock; +import androidx.annotation.NonNull; + import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; import org.monkey.d.ruffy.ruffy.driver.display.MenuType; import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuTime; -import org.slf4j.Logger; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import info.nightscout.shared.logging.StacktraceLoggerWrapper; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.PumpState; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.PumpWarningCodes; import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.WarningOrErrorCode; +import info.nightscout.shared.logging.AAPSLogger; +import info.nightscout.shared.logging.LTag; public class SetTbrCommand extends BaseCommand { - private static final Logger log = StacktraceLoggerWrapper.getLogger(SetTbrCommand.class); + private final AAPSLogger aapsLogger; private final long percentage; private final long duration; - public SetTbrCommand(long percentage, long duration) { + public SetTbrCommand(long percentage, long duration, AAPSLogger aapsLogger) { this.percentage = percentage; this.duration = duration; + this.aapsLogger = aapsLogger; } @Override @@ -116,7 +119,7 @@ public class SetTbrCommand extends BaseCommand { PumpState state = scripter.readPumpStateInternal(); if (state.tbrRemainingDuration == 1) { while (state.tbrActive && System.currentTimeMillis() < timeout) { - log.debug("Waiting for existing TBR to run out to avoid alert while setting TBR"); + aapsLogger.debug(LTag.PUMP, "Waiting for existing TBR to run out to avoid alert while setting TBR"); scripter.waitForScreenUpdate(); state = scripter.readPumpStateInternal(); } @@ -140,14 +143,14 @@ public class SetTbrCommand extends BaseCommand { private boolean inputTbrPercentage() { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); long currentPercent = readDisplayedPercentage(); - log.debug("Current TBR %: " + currentPercent); + aapsLogger.debug(LTag.PUMP, "Current TBR %: " + currentPercent); long percentageChange = percentage - currentPercent; long percentageSteps = percentageChange / 10; boolean increasePercentage = percentageSteps > 0; - log.debug("Pressing " + (increasePercentage ? "up" : "down") + " " + percentageSteps + " times"); + aapsLogger.debug(LTag.PUMP, "Pressing " + (increasePercentage ? "up" : "down") + " " + percentageSteps + " times"); for (int i = 0; i < Math.abs(percentageSteps); i++) { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - log.debug("Push #" + (i + 1) + "/" + Math.abs(percentageSteps)); + aapsLogger.debug(LTag.PUMP, "Push #" + (i + 1) + "/" + Math.abs(percentageSteps)); if (increasePercentage) scripter.pressUpKey(); else scripter.pressDownKey(); SystemClock.sleep(50); @@ -163,13 +166,13 @@ public class SetTbrCommand extends BaseCommand { while (timeout > System.currentTimeMillis() && ((increasingPercentage && displayedPercentage < percentage) || (!increasingPercentage && displayedPercentage > percentage))) { - log.debug("Waiting for pump to process scrolling input for percentage, current: " + aapsLogger.debug(LTag.PUMP, "Waiting for pump to process scrolling input for percentage, current: " + displayedPercentage + ", desired: " + percentage + ", scrolling " + (increasingPercentage ? "up" : "down")); SystemClock.sleep(50); displayedPercentage = readDisplayedPercentage(); } - log.debug("Final displayed TBR percentage: " + displayedPercentage); + aapsLogger.debug(LTag.PUMP, "Final displayed TBR percentage: " + displayedPercentage); if (displayedPercentage != percentage) { throw new CommandException("Failed to set TBR percentage, requested: " + percentage + ", actual: " + displayedPercentage); @@ -179,11 +182,11 @@ public class SetTbrCommand extends BaseCommand { // value due to due scrolling taking extremely long SystemClock.sleep(1000); scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long refreshedDisplayedTbrPecentage = readDisplayedPercentage(); - if (displayedPercentage != refreshedDisplayedTbrPecentage) { + long refreshedDisplayedTbrPercentage = readDisplayedPercentage(); + if (displayedPercentage != refreshedDisplayedTbrPercentage) { throw new CommandException("Failed to set TBR percentage: " + "percentage changed after input stopped from " - + displayedPercentage + " -> " + refreshedDisplayedTbrPecentage); + + displayedPercentage + " -> " + refreshedDisplayedTbrPercentage); } } @@ -191,10 +194,10 @@ public class SetTbrCommand extends BaseCommand { scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); long durationSteps = calculateDurationSteps(); boolean increaseDuration = durationSteps > 0; - log.debug("Pressing " + (increaseDuration ? "up" : "down") + " " + durationSteps + " times"); + aapsLogger.debug(LTag.PUMP, "Pressing " + (increaseDuration ? "up" : "down") + " " + durationSteps + " times"); for (int i = 0; i < Math.abs(durationSteps); i++) { scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - log.debug("Push #" + (i + 1) + "/" + Math.abs(durationSteps)); + aapsLogger.debug(LTag.PUMP, "Push #" + (i + 1) + "/" + Math.abs(durationSteps)); if (increaseDuration) scripter.pressUpKey(); else scripter.pressDownKey(); SystemClock.sleep(50); @@ -204,7 +207,7 @@ public class SetTbrCommand extends BaseCommand { private long calculateDurationSteps() { long currentDuration = readDisplayedDuration(); - log.debug("Initial TBR duration: " + currentDuration); + aapsLogger.debug(LTag.PUMP, "Initial TBR duration: " + currentDuration); long difference = duration - currentDuration; long durationSteps = difference / 15; @@ -224,14 +227,14 @@ public class SetTbrCommand extends BaseCommand { while (timeout > System.currentTimeMillis() && ((increasingPercentage && displayedDuration < duration) || (!increasingPercentage && displayedDuration > duration))) { - log.debug("Waiting for pump to process scrolling input for duration, current: " + aapsLogger.debug(LTag.PUMP, "Waiting for pump to process scrolling input for duration, current: " + displayedDuration + ", desired: " + duration + ", scrolling " + (increasingPercentage ? "up" : "down")); SystemClock.sleep(50); displayedDuration = readDisplayedDuration(); } - log.debug("Final displayed TBR duration: " + displayedDuration); + aapsLogger.debug(LTag.PUMP, "Final displayed TBR duration: " + displayedDuration); if (displayedDuration != duration) { throw new CommandException("Failed to set TBR duration, requested: " + duration + ", actual: " + displayedDuration); @@ -264,7 +267,7 @@ public class SetTbrCommand extends BaseCommand { private long readDisplayedDuration() { MenuTime duration = scripter.readBlinkingValue(MenuTime.class, MenuAttribute.RUNTIME); - return duration.getHour() * 60 + duration.getMinute(); + return duration.getHour() * 60L + duration.getMinute(); } private long readDisplayedPercentage() { @@ -276,7 +279,7 @@ public class SetTbrCommand extends BaseCommand { return true; } - @Override + @NonNull @Override public String toString() { return "SetTbrCommand{" + "percentage=" + percentage + diff --git a/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperImplementation.kt b/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperImplementation.kt index 7224b4ec00..86673862f4 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperImplementation.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/resources/ResourceHelperImplementation.kt @@ -28,7 +28,7 @@ class ResourceHelperImplementation @Inject constructor(private val context: Cont } catch (exception: Exception) { val resourceName = context.resources.getResourceEntryName(id) val resourceValue = context.getString(id) - val currentLocale: Locale = context.resources.configuration.locale + val currentLocale: Locale = context.resources.configuration.locales[0] fabricPrivacy.logMessage("Failed to get string for resource $resourceName ($id) '$resourceValue' for locale $currentLocale with args ${args.map{it.toString()}}") fabricPrivacy.logException(exception) try { From fabcc741fc9b3048c217e9ab21cc5f56d8e36091 Mon Sep 17 00:00:00 2001 From: Philoul Date: Sun, 20 Feb 2022 21:01:59 +0100 Subject: [PATCH 19/40] Fix Size and layout for TT icon in Wizard --- app/src/main/res/layout/dialog_wizard.xml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/src/main/res/layout/dialog_wizard.xml b/app/src/main/res/layout/dialog_wizard.xml index 4c582cc559..2ec56be3f9 100644 --- a/app/src/main/res/layout/dialog_wizard.xml +++ b/app/src/main/res/layout/dialog_wizard.xml @@ -266,11 +266,10 @@ android:id="@+id/tt_checkbox_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center_vertical" - android:paddingStart="5dp" - android:paddingEnd="5dp" - android:scaleX="0.7" - android:scaleY="0.7" + android:layout_marginLeft="15dp" + android:layout_marginRight="15dp" + android:scaleX="1.6" + android:scaleY="1.6" android:button="@drawable/checkbox_tt_icon" android:checked="true" android:visibility="gone" From 7459adbcc6d5f59df99e02f36f6c114219257bfb Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 20 Feb 2022 21:48:47 +0100 Subject: [PATCH 20/40] DynamicISF: prevent crash with no TDD --- .../DetermineBasalAdapterSMBDynamicISFJS.kt | 2 +- .../androidaps/utils/stats/TddCalculator.kt | 26 ++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt index 5bdee7d474..317a7159b0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMBDynamicISF/DetermineBasalAdapterSMBDynamicISFJS.kt @@ -258,7 +258,7 @@ class DetermineBasalAdapterSMBDynamicISFJS internal constructor(private val scri this.mealData.put("lastBolusTime", mealData.lastBolusTime) this.mealData.put("lastCarbTime", mealData.lastCarbTime) - this.mealData.put("TDDAIMI7", tddCalculator.averageTDD(tddCalculator.calculate(7)).totalAmount) + this.mealData.put("TDDAIMI7", tddCalculator.averageTDD(tddCalculator.calculate(7))?.totalAmount) this.mealData.put("TDDPUMP", tddCalculator.calculateDaily().totalAmount) this.mealData.put("TDDLast24", tddCalculator.calculate24Daily().totalAmount) diff --git a/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt b/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt index 05b1226c1b..349dd597c7 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/stats/TddCalculator.kt @@ -6,18 +6,18 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.Bolus import info.nightscout.androidaps.database.entities.TotalDailyDose +import info.nightscout.androidaps.extensions.convertedToAbsolute +import info.nightscout.androidaps.extensions.toText import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.IobCobCalculator import info.nightscout.androidaps.interfaces.ProfileFunction -import info.nightscout.shared.logging.AAPSLogger -import info.nightscout.shared.logging.LTag import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.HtmlHelper import info.nightscout.androidaps.utils.MidnightTime import info.nightscout.androidaps.utils.T -import info.nightscout.androidaps.extensions.convertedToAbsolute -import info.nightscout.androidaps.extensions.toText import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.shared.logging.AAPSLogger +import info.nightscout.shared.logging.LTag import javax.inject.Inject class TddCalculator @Inject constructor( @@ -76,8 +76,8 @@ class TddCalculator @Inject constructor( return result } - fun calculateDaily():TotalDailyDose { - val startTime = MidnightTime.calc(dateUtil.now() ) + fun calculateDaily(): TotalDailyDose { + val startTime = MidnightTime.calc(dateUtil.now()) val endTime = dateUtil.now() val tdd = TotalDailyDose(timestamp = startTime) //val result = TotalDailyDose() @@ -118,12 +118,12 @@ class TddCalculator @Inject constructor( tdd.totalAmount = tdd.bolusAmount + tdd.basalAmount //} - aapsLogger.debug(LTag.CORE, tdd.toString()) return tdd } - fun calculate24Daily():TotalDailyDose { - val startTime = dateUtil.now() - T.hours(hour = 24).msecs() + + fun calculate24Daily(): TotalDailyDose { + val startTime = dateUtil.now() - T.hours(hour = 24).msecs() val endTime = dateUtil.now() val tdd = TotalDailyDose(timestamp = startTime) //val result = TotalDailyDose() @@ -165,12 +165,13 @@ class TddCalculator @Inject constructor( tdd.totalAmount = tdd.bolusAmount + tdd.basalAmount //} - aapsLogger.debug(LTag.CORE, tdd.toString()) return tdd } - fun averageTDD(tdds: LongSparseArray): TotalDailyDose { + + fun averageTDD(tdds: LongSparseArray): TotalDailyDose? { val totalTdd = TotalDailyDose(timestamp = dateUtil.now()) + if (tdds.size() == 0) return null for (i in 0 until tdds.size()) { val tdd = tdds.valueAt(i) totalTdd.basalAmount += tdd.basalAmount @@ -189,10 +190,11 @@ class TddCalculator @Inject constructor( val tdds = calculate(7) val averageTdd = averageTDD(tdds) return HtmlHelper.fromHtml( - "" + rh.gs(R.string.tdd) + ":
" + + if (averageTdd != null) "" + rh.gs(R.string.tdd) + ":
" + toText(tdds, true) + "" + rh.gs(R.string.average) + ":
" + averageTdd.toText(rh, tdds.size(), true) + else "" ) } From d39e9e9cf321d1f5d6e9c474a43dc48bdfdb2819 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 21 Feb 2022 13:47:36 +0100 Subject: [PATCH 21/40] fix tests --- .../androidaps/interfaces/ConstraintsCheckerTest.kt | 11 +++++++++-- .../plugins/constraints/safety/SafetyPluginTest.kt | 5 ++++- .../androidaps/plugins/pump/combo/ComboPluginTest.kt | 4 +++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt b/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt index 4c6c4d1ec6..bf0959fdd5 100644 --- a/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/interfaces/ConstraintsCheckerTest.kt @@ -14,6 +14,7 @@ import info.nightscout.androidaps.insight.database.InsightDbHelper import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin +import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.OpenAPSSMBDynamicISFPlugin import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective @@ -21,6 +22,7 @@ import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin import info.nightscout.androidaps.plugins.general.maintenance.PrefFileListProvider import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatusProvider import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin +import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.RuffyScripter import info.nightscout.androidaps.plugins.pump.common.bolusInfo.DetailedBolusInfoStorage import info.nightscout.androidaps.plugins.pump.common.bolusInfo.TemporaryBasalStorage import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin @@ -29,6 +31,7 @@ import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin import info.nightscout.androidaps.plugins.source.GlimpPlugin import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.Profiler +import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.buildHelper.BuildHelperImpl import info.nightscout.shared.sharedPreferences.SP import org.junit.Assert @@ -57,6 +60,8 @@ class ConstraintsCheckerTest : TestBaseWithProfile() { @Mock lateinit var repository: AppRepository @Mock lateinit var pumpSync: PumpSync @Mock lateinit var insightDatabaseDao: InsightDatabaseDao + @Mock lateinit var ruffyScripter: RuffyScripter + @Mock lateinit var buildHelper: BuildHelper private lateinit var danaPump: DanaPump private lateinit var insightDbHelper: InsightDbHelper @@ -69,6 +74,7 @@ class ConstraintsCheckerTest : TestBaseWithProfile() { private lateinit var insightPlugin: LocalInsightPlugin private lateinit var openAPSSMBPlugin: OpenAPSSMBPlugin private lateinit var openAPSAMAPlugin: OpenAPSAMAPlugin + private lateinit var openAPSSMBDynamicISFPlugin: OpenAPSSMBDynamicISFPlugin private lateinit var hardLimits: HardLimits val injector = HasAndroidInjector { @@ -131,13 +137,14 @@ class ConstraintsCheckerTest : TestBaseWithProfile() { danaPump = DanaPump(aapsLogger, sp, dateUtil, injector) hardLimits = HardLimits(aapsLogger, rxBus, sp, rh, context, repository) objectivesPlugin = ObjectivesPlugin(injector, aapsLogger, rh, activePlugin, sp, config, dateUtil, uel) - comboPlugin = ComboPlugin(injector, aapsLogger, rxBus, rh, profileFunction, sp, commandQueue, context, pumpSync, dateUtil) + comboPlugin = ComboPlugin(injector, aapsLogger, rxBus, rh, profileFunction, sp, commandQueue, context, pumpSync, dateUtil, ruffyScripter) danaRPlugin = DanaRPlugin(injector, aapsLogger, aapsSchedulers, rxBus, context, rh, constraintChecker, activePlugin, sp, commandQueue, danaPump, dateUtil, fabricPrivacy, pumpSync) danaRSPlugin = DanaRSPlugin(injector, aapsLogger, aapsSchedulers, rxBus, context, rh, constraintChecker, profileFunction, sp, commandQueue, danaPump, pumpSync, detailedBolusInfoStorage, temporaryBasalStorage, fabricPrivacy, dateUtil) insightPlugin = LocalInsightPlugin(injector, aapsLogger, rxBus, rh, sp, commandQueue, profileFunction, context, config, dateUtil, insightDbHelper, pumpSync) openAPSSMBPlugin = OpenAPSSMBPlugin(injector, aapsLogger, rxBus, constraintChecker, rh, profileFunction, context, activePlugin, iobCobCalculator, hardLimits, profiler, sp, dateUtil, repository, glucoseStatusProvider) + openAPSSMBDynamicISFPlugin = OpenAPSSMBDynamicISFPlugin(injector, aapsLogger, rxBus, constraintChecker, rh, profileFunction, context, activePlugin, iobCobCalculator, hardLimits, profiler, sp, dateUtil, repository, glucoseStatusProvider, buildHelper) openAPSAMAPlugin = OpenAPSAMAPlugin(injector, aapsLogger, rxBus, constraintChecker, rh, profileFunction, context, activePlugin, iobCobCalculator, hardLimits, profiler, fabricPrivacy, dateUtil, repository, glucoseStatusProvider) - safetyPlugin = SafetyPlugin(injector, aapsLogger, rh, sp, rxBus, constraintChecker, openAPSAMAPlugin, openAPSSMBPlugin, sensitivityOref1Plugin, activePlugin, hardLimits, BuildHelperImpl(config, fileListProvider), iobCobCalculator, config, dateUtil) + safetyPlugin = SafetyPlugin(injector, aapsLogger, rh, sp, rxBus, constraintChecker, openAPSAMAPlugin, openAPSSMBPlugin, openAPSSMBDynamicISFPlugin, sensitivityOref1Plugin, activePlugin, hardLimits, BuildHelperImpl(config, fileListProvider), iobCobCalculator, config, dateUtil) val constraintsPluginsList = ArrayList() constraintsPluginsList.add(safetyPlugin) constraintsPluginsList.add(objectivesPlugin) diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPluginTest.kt b/app/src/test/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPluginTest.kt index f21efddce0..6d868075c4 100644 --- a/app/src/test/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPluginTest.kt +++ b/app/src/test/java/info/nightscout/androidaps/plugins/constraints/safety/SafetyPluginTest.kt @@ -11,6 +11,7 @@ import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.interfaces.PumpDescription import info.nightscout.androidaps.plugins.aps.openAPSAMA.OpenAPSAMAPlugin import info.nightscout.androidaps.plugins.aps.openAPSSMB.OpenAPSSMBPlugin +import info.nightscout.androidaps.plugins.aps.openAPSSMBDynamicISF.OpenAPSSMBDynamicISFPlugin import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref1Plugin @@ -30,6 +31,7 @@ class SafetyPluginTest : TestBaseWithProfile() { @Mock lateinit var constraintChecker: ConstraintChecker @Mock lateinit var openAPSAMAPlugin: OpenAPSAMAPlugin @Mock lateinit var openAPSSMBPlugin: OpenAPSSMBPlugin + @Mock lateinit var openAPSSMBDynamicISFPlugin: OpenAPSSMBDynamicISFPlugin @Mock lateinit var sensitivityOref1Plugin: SensitivityOref1Plugin @Mock lateinit var activePlugin: ActivePlugin @Mock lateinit var buildHelper: BuildHelper @@ -69,7 +71,8 @@ class SafetyPluginTest : TestBaseWithProfile() { `when`(virtualPumpPlugin.pumpDescription).thenReturn(pumpDescription) hardLimits = HardLimits(aapsLogger, rxBus, sp, rh, context, repository) `when`(config.APS).thenReturn(true) - safetyPlugin = SafetyPlugin(injector, aapsLogger, rh, sp, rxBus, constraintChecker, openAPSAMAPlugin, openAPSSMBPlugin, sensitivityOref1Plugin, activePlugin, hardLimits, buildHelper, + safetyPlugin = SafetyPlugin(injector, aapsLogger, rh, sp, rxBus, constraintChecker, openAPSAMAPlugin, openAPSSMBPlugin, openAPSSMBDynamicISFPlugin, sensitivityOref1Plugin, activePlugin, + hardLimits, buildHelper, iobCobCalculator, config, dateUtil) } diff --git a/combo/src/test/java/info/nightscout/androidaps/plugins/pump/combo/ComboPluginTest.kt b/combo/src/test/java/info/nightscout/androidaps/plugins/pump/combo/ComboPluginTest.kt index 1b0b39e742..debaf34b2d 100644 --- a/combo/src/test/java/info/nightscout/androidaps/plugins/pump/combo/ComboPluginTest.kt +++ b/combo/src/test/java/info/nightscout/androidaps/plugins/pump/combo/ComboPluginTest.kt @@ -8,6 +8,7 @@ import info.nightscout.androidaps.combo.R import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.interfaces.* import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.RuffyScripter import info.nightscout.androidaps.plugins.pump.combo.ruffyscripter.history.Bolus import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.resources.ResourceHelper @@ -28,6 +29,7 @@ class ComboPluginTest : TestBase() { @Mock lateinit var sp: SP @Mock lateinit var context: Context @Mock lateinit var dateUtil: DateUtil + @Mock lateinit var ruffyScripter: RuffyScripter val injector = HasAndroidInjector { AndroidInjector { @@ -43,7 +45,7 @@ class ComboPluginTest : TestBase() { fun prepareMocks() { `when`(rh.gs(R.string.novalidbasalrate)).thenReturn("No valid basal rate read from pump") `when`(rh.gs(R.string.combo_pump_unsupported_operation)).thenReturn("Requested operation not supported by pump") - comboPlugin = ComboPlugin(injector, aapsLogger, RxBus(aapsSchedulers, aapsLogger), rh, profileFunction, sp, commandQueue, context, pumpSync, dateUtil) + comboPlugin = ComboPlugin(injector, aapsLogger, RxBus(aapsSchedulers, aapsLogger), rh, profileFunction, sp, commandQueue, context, pumpSync, dateUtil, ruffyScripter) } @Test From 67e5fb8dc753067baf79520e523d206759dc516a Mon Sep 17 00:00:00 2001 From: Andries Smit Date: Tue, 22 Feb 2022 21:11:15 +0100 Subject: [PATCH 22/40] Add history treatments option menu --- .../activities/TreatmentsActivity.kt | 24 +- .../fragments/TreatmentsBolusCarbsFragment.kt | 360 +++++++++++------- .../fragments/TreatmentsCareportalFragment.kt | 224 +++++++---- .../TreatmentsExtendedBolusesFragment.kt | 162 ++++++-- .../TreatmentsProfileSwitchFragment.kt | 258 +++++++++---- .../fragments/TreatmentsTempTargetFragment.kt | 222 ++++++++--- .../TreatmentsTemporaryBasalsFragment.kt | 200 +++++++--- .../fragments/TreatmentsUserEntryFragment.kt | 95 +++-- .../treatments_bolus_carbs_fragment.xml | 44 --- .../layout/treatments_bolus_carbs_item.xml | 18 +- .../layout/treatments_careportal_fragment.xml | 44 --- .../res/layout/treatments_careportal_item.xml | 10 +- .../treatments_extendedbolus_fragment.xml | 24 -- .../layout/treatments_extendedbolus_item.xml | 10 +- .../main/res/layout/treatments_fragment.xml | 7 + .../treatments_profileswitch_fragment.xml | 34 -- .../layout/treatments_profileswitch_item.xml | 11 +- .../layout/treatments_tempbasals_fragment.xml | 26 -- .../res/layout/treatments_tempbasals_item.xml | 11 +- .../layout/treatments_temptarget_fragment.xml | 35 -- .../res/layout/treatments_temptarget_item.xml | 10 +- .../layout/treatments_user_entry_fragment.xml | 34 -- .../main/res/menu/menu_delete_selection.xml | 11 + .../res/menu/menu_treatments_carbs_bolus.xml | 25 ++ .../res/menu/menu_treatments_careportal.xml | 25 ++ .../menu/menu_treatments_extended_bolus.xml | 17 + .../menu/menu_treatments_profile_switch.xml | 17 + .../res/menu/menu_treatments_temp_basal.xml | 17 + .../res/menu/menu_treatments_temp_target.xml | 21 + .../res/menu/menu_treatments_user_entry.xml | 17 + app/src/main/res/values/strings.xml | 13 + core/src/main/res/drawable/ic_close.xml | 5 + core/src/main/res/values/layout.xml | 2 + core/src/main/res/values/strings.xml | 1 + 34 files changed, 1289 insertions(+), 745 deletions(-) create mode 100644 app/src/main/res/menu/menu_delete_selection.xml create mode 100644 app/src/main/res/menu/menu_treatments_carbs_bolus.xml create mode 100644 app/src/main/res/menu/menu_treatments_careportal.xml create mode 100644 app/src/main/res/menu/menu_treatments_extended_bolus.xml create mode 100644 app/src/main/res/menu/menu_treatments_profile_switch.xml create mode 100644 app/src/main/res/menu/menu_treatments_temp_basal.xml create mode 100644 app/src/main/res/menu/menu_treatments_temp_target.xml create mode 100644 app/src/main/res/menu/menu_treatments_user_entry.xml create mode 100644 core/src/main/res/drawable/ic_close.xml diff --git a/app/src/main/java/info/nightscout/androidaps/activities/TreatmentsActivity.kt b/app/src/main/java/info/nightscout/androidaps/activities/TreatmentsActivity.kt index 9a68aeaf5f..5290b48711 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/TreatmentsActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/TreatmentsActivity.kt @@ -1,13 +1,13 @@ package info.nightscout.androidaps.activities import android.os.Bundle +import android.view.MenuItem import android.view.View import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentTransaction import info.nightscout.androidaps.R import info.nightscout.androidaps.activities.fragments.* import info.nightscout.androidaps.databinding.TreatmentsFragmentBinding -import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.utils.buildHelper.BuildHelper import javax.inject.Inject @@ -23,40 +23,60 @@ class TreatmentsActivity : NoSplashAppCompatActivity() { super.onCreate(savedInstanceState) binding = TreatmentsFragmentBinding.inflate(layoutInflater) setContentView(binding.root) - //binding.tempBasals.visibility = buildHelper.isEngineeringMode().toVisibility() //binding.extendedBoluses.visibility = (buildHelper.isEngineeringMode() && !activePlugin.activePump.isFakingTempsByExtendedBoluses).toVisibility() binding.treatments.setOnClickListener { setFragment(TreatmentsBolusCarbsFragment()) setBackgroundColorOnSelected(it) + supportActionBar?.title = rh.gs(R.string.carbs_and_bolus) } binding.extendedBoluses.setOnClickListener { setFragment(TreatmentsExtendedBolusesFragment()) setBackgroundColorOnSelected(it) + supportActionBar?.title = rh.gs(R.string.extended_bolus) } binding.tempBasals.setOnClickListener { setFragment(TreatmentsTemporaryBasalsFragment()) setBackgroundColorOnSelected(it) + supportActionBar?.title = rh.gs(R.string.tempbasal_label) } binding.tempTargets.setOnClickListener { setFragment(TreatmentsTempTargetFragment()) setBackgroundColorOnSelected(it) + supportActionBar?.title = rh.gs(R.string.tempt_targets) } binding.profileSwitches.setOnClickListener { setFragment(TreatmentsProfileSwitchFragment()) setBackgroundColorOnSelected(it) + supportActionBar?.title = rh.gs(R.string.profile_changes) } binding.careportal.setOnClickListener { setFragment(TreatmentsCareportalFragment()) setBackgroundColorOnSelected(it) + supportActionBar?.title = rh.gs(R.string.careportal) } binding.userentry.setOnClickListener { setFragment(TreatmentsUserEntryFragment()) setBackgroundColorOnSelected(it) + supportActionBar?.title = rh.gs(R.string.user_action) } setFragment(TreatmentsBolusCarbsFragment()) setBackgroundColorOnSelected(binding.treatments) + setSupportActionBar(binding.toolbar) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + supportActionBar?.title = rh.gs(R.string.carbs_and_bolus) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + android.R.id.home -> { + finish() + true + } + + else -> false + } } private fun setFragment(selectedFragment: Fragment) { diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt index 3ed805966e..dd359ef07d 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt @@ -3,9 +3,10 @@ package info.nightscout.androidaps.activities.fragments import android.annotation.SuppressLint import android.graphics.Paint import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup +import android.view.* +import android.widget.CompoundButton +import android.view.ActionMode +import androidx.appcompat.widget.Toolbar import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment @@ -79,9 +80,14 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { private var _binding: TreatmentsBolusCarbsFragmentBinding? = null - // This property is only valid between onCreateView and - // onDestroyView. + // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! + private var selectedItems: MutableList = mutableListOf() + private var showInvalidated = false + private var removeActionMode: ActionMode? = null + + // val TAG = "TreatmentMenu" + private var toolbar: Toolbar? = null override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = TreatmentsBolusCarbsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root @@ -89,92 +95,10 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { @SuppressLint("CheckResult") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + setHasOptionsMenu(true) + toolbar = activity?.findViewById(R.id.toolbar) binding.recyclerview.setHasFixedSize(true) binding.recyclerview.layoutManager = LinearLayoutManager(view.context) - - binding.refreshFromNightscout.setOnClickListener { - activity?.let { activity -> - OKDialog.showConfirmation(activity, rh.gs(R.string.refresheventsfromnightscout) + "?") { - uel.log(Action.TREATMENTS_NS_REFRESH, Sources.Treatments) - disposable += - Completable.fromAction { - repository.deleteAllBolusCalculatorResults() - repository.deleteAllBoluses() - repository.deleteAllCarbs() - } - .subscribeOn(aapsSchedulers.io) - .observeOn(aapsSchedulers.main) - .subscribeBy( - onError = { aapsLogger.error("Error removing entries", it) }, - onComplete = { - rxBus.send(EventTreatmentChange()) - rxBus.send(EventNewHistoryData(0, false)) - } - ) - rxBus.send(EventNSClientRestart()) - } - } - } - binding.deleteFutureTreatments.setOnClickListener { - activity?.let { activity -> - OKDialog.showConfirmation(activity, rh.gs(R.string.overview_treatment_label), rh.gs(R.string.deletefuturetreatments) + "?", Runnable { - uel.log(Action.DELETE_FUTURE_TREATMENTS, Sources.Treatments) - repository - .getBolusesDataFromTime(dateUtil.now(), false) - .observeOn(aapsSchedulers.main) - .subscribe { list -> - list.forEach { bolus -> - disposable += repository.runTransactionForResult(InvalidateBolusTransaction(bolus.id)) - .subscribe( - { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bolus $it") } }, - { aapsLogger.error(LTag.DATABASE, "Error while invalidating bolus", it) } - ) - } - } - repository - .getCarbsDataFromTimeNotExpanded(dateUtil.now(), false) - .observeOn(aapsSchedulers.main) - .subscribe { list -> - list.forEach { carb -> - if (carb.duration == 0L) - disposable += repository.runTransactionForResult(InvalidateCarbsTransaction(carb.id)) - .subscribe( - { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") } }, - { aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) } - ) - else { - disposable += repository.runTransactionForResult(CutCarbsTransaction(carb.id, dateUtil.now())) - .subscribe( - { result -> - result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") } - result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated (cut end) carbs $it") } - }, - { aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) } - ) - } - } - } - repository - .getBolusCalculatorResultsDataFromTime(dateUtil.now(), false) - .observeOn(aapsSchedulers.main) - .subscribe { list -> - list.forEach { bolusCalc -> - disposable += repository.runTransactionForResult(InvalidateBolusCalculatorResultTransaction(bolusCalc.id)) - .subscribe( - { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bolusCalculatorResult $it") } }, - { aapsLogger.error(LTag.DATABASE, "Error while invalidating bolusCalculatorResult", it) } - ) - } - } - binding.deleteFutureTreatments.visibility = View.GONE - }) - } - } - val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_insulin, false) || !sp.getBoolean(R.string.key_ns_receive_carbs, false) || !buildHelper.isEngineeringMode() - if (nsUploadOnly) binding.refreshFromNightscout.visibility = View.GONE - binding.showInvalidated.setOnCheckedChangeListener { _, _ -> - rxBus.send(EventTreatmentUpdateGui()) - } } private fun bolusMealLinksWithInvalid(now: Long) = repository @@ -204,8 +128,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { fun swapAdapter() { val now = System.currentTimeMillis() - if (binding.showInvalidated.isChecked) - disposable += carbsMealLinksWithInvalid(now) + disposable += if (showInvalidated) + carbsMealLinksWithInvalid(now) .zipWith(bolusMealLinksWithInvalid(now)) { first, second -> first + second } .zipWith(calcResultMealLinksWithInvalid(now)) { first, second -> first + second } .map { ml -> @@ -217,10 +141,9 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { .observeOn(aapsSchedulers.main) .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) - binding.deleteFutureTreatments.visibility = list.isNotEmpty().toVisibility() } else - disposable += carbsMealLinks(now) + carbsMealLinks(now) .zipWith(bolusMealLinks(now)) { first, second -> first + second } .zipWith(calcResultMealLinks(now)) { first, second -> first + second } .map { ml -> @@ -232,7 +155,6 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { .observeOn(aapsSchedulers.main) .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) - binding.deleteFutureTreatments.visibility = list.isNotEmpty().toVisibility() } } @@ -267,13 +189,14 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() + removeActionMode?.let { it.finish() } binding.recyclerview.adapter = null // avoid leaks _binding = null } - private fun timestamp(ml: MealLink): Long = ml.bolusCalculatorResult?.let { it.timestamp } ?: ml.bolus?.let { it.timestamp } ?: ml.carbs?.let { it.timestamp } ?: 0L + private fun timestamp(ml: MealLink): Long = ml.bolusCalculatorResult?.timestamp ?: ml.bolus?.timestamp ?: ml.carbs?.timestamp ?: 0L - inner class RecyclerViewAdapter internal constructor(var mealLinks: List) : RecyclerView.Adapter() { + inner class RecyclerViewAdapter internal constructor(private var mealLinks: List) : RecyclerView.Adapter() { override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MealLinkLoadedViewHolder = MealLinkLoadedViewHolder(LayoutInflater.from(viewGroup.context).inflate(R.layout.treatments_bolus_carbs_item, viewGroup, false)) @@ -287,13 +210,13 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { holder.binding.date.text = dateUtil.dateString(timestamp(ml)) // Metadata - holder.binding.metadataLayout.visibility = (ml.bolusCalculatorResult != null && (ml.bolusCalculatorResult.isValid || binding.showInvalidated.isChecked)).toVisibility() + holder.binding.metadataLayout.visibility = (ml.bolusCalculatorResult != null && (ml.bolusCalculatorResult.isValid || showInvalidated)).toVisibility() ml.bolusCalculatorResult?.let { bolusCalculatorResult -> holder.binding.calcTime.text = dateUtil.timeString(bolusCalculatorResult.timestamp) } // Bolus - holder.binding.bolusLayout.visibility = (ml.bolus != null && (ml.bolus.isValid || binding.showInvalidated.isChecked)).toVisibility() + holder.binding.bolusLayout.visibility = (ml.bolus != null && (ml.bolus.isValid || showInvalidated)).toVisibility() ml.bolus?.let { bolus -> holder.binding.bolusTime.text = dateUtil.timeString(bolus.timestamp) holder.binding.insulin.text = rh.gs(R.string.formatinsulinunits, bolus.amount) @@ -321,7 +244,7 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { } } // Carbs - holder.binding.carbsLayout.visibility = (ml.carbs != null && (ml.carbs.isValid || binding.showInvalidated.isChecked)).toVisibility() + holder.binding.carbsLayout.visibility = (ml.carbs != null && (ml.carbs.isValid || showInvalidated)).toVisibility() ml.carbs?.let { carbs -> holder.binding.carbsTime.text = dateUtil.timeString(carbs.timestamp) holder.binding.carbs.text = rh.gs(R.string.format_carbs, carbs.amount.toInt()) @@ -331,18 +254,26 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { holder.binding.carbsInvalid.visibility = carbs.isValid.not().toVisibility() } - holder.binding.bolusRemove.visibility = (ml.bolus?.isValid == true).toVisibility() - holder.binding.carbsRemove.visibility = (ml.carbs?.isValid == true).toVisibility() - holder.binding.bolusRemove.tag = ml - holder.binding.carbsRemove.tag = ml + val onChange = CompoundButton.OnCheckedChangeListener { _, value -> + if (value) { + selectedItems.add(ml) + } else { + selectedItems.remove(ml) + } + removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size) + } + holder.binding.cbBolusRemove.visibility = ((ml.bolus?.isValid == true) && (removeActionMode != null)).toVisibility() + holder.binding.cbBolusRemove.setOnCheckedChangeListener(onChange) + + holder.binding.cbCarbsRemove.visibility = (ml.carbs?.isValid == true && (removeActionMode != null)).toVisibility() + holder.binding.cbCarbsRemove.setOnCheckedChangeListener(onChange) + holder.binding.calculation.tag = ml val nextTimestamp = if (mealLinks.size != position + 1) timestamp(mealLinks[position + 1]) else 0L holder.binding.delimiter.visibility = dateUtil.isSameDay(timestamp(ml), nextTimestamp).toVisibility() } - override fun getItemCount(): Int { - return mealLinks.size - } + override fun getItemCount() = mealLinks.size inner class MealLinkLoadedViewHolder internal constructor(view: View) : RecyclerView.ViewHolder(view) { @@ -359,35 +290,203 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { } } binding.calculation.paintFlags = binding.calculation.paintFlags or Paint.UNDERLINE_TEXT_FLAG - binding.bolusRemove.setOnClickListener { ml -> - val bolus = (ml.tag as MealLink?)?.bolus ?: return@setOnClickListener - activity?.let { activity -> - val text = rh.gs(R.string.configbuilder_insulin) + ": " + - rh.gs(R.string.formatinsulinunits, bolus.amount) + "\n" + - rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(bolus.timestamp) - OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), text, Runnable { + } + } + } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.menu_treatments_carbs_bolus, menu) + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onPrepareOptionsMenu(menu: Menu) { + menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated + menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated + val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_insulin, false) || !sp.getBoolean(R.string.key_ns_receive_carbs, false) || !buildHelper.isEngineeringMode() + menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly + val hasItems = (binding.recyclerview.adapter?.itemCount ?: 0) > 0 + menu.findItem(R.id.nav_delete_future)?.isVisible = hasItems + + return super.onPrepareOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.nav_remove_items -> { + removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback()) + true + } + + R.id.nav_show_invalidated -> { + showInvalidated = true + rxBus.send(EventTreatmentUpdateGui()) + true + } + + R.id.nav_hide_invalidated -> { + showInvalidated = false + rxBus.send(EventTreatmentUpdateGui()) + true + } + + R.id.nav_delete_future -> { + deleteFutureTreatments() + true + } + + R.id.nav_refresh_ns -> { + refreshFromNightScout() + true + } + + else -> false + } + } + + private fun refreshFromNightScout() { + activity?.let { activity -> + OKDialog.showConfirmation(activity, rh.gs(R.string.refresheventsfromnightscout) + "?") { + uel.log(Action.TREATMENTS_NS_REFRESH, Sources.Treatments) + disposable += + Completable.fromAction { + repository.deleteAllBolusCalculatorResults() + repository.deleteAllBoluses() + repository.deleteAllCarbs() + } + .subscribeOn(aapsSchedulers.io) + .observeOn(aapsSchedulers.main) + .subscribeBy( + onError = { aapsLogger.error("Error removing entries", it) }, + onComplete = { + rxBus.send(EventTreatmentChange()) + rxBus.send(EventNewHistoryData(0, false)) + } + ) + rxBus.send(EventNSClientRestart()) + } + } + } + + fun deleteFutureTreatments() { + activity?.let { activity -> + OKDialog.showConfirmation(activity, rh.gs(R.string.overview_treatment_label), rh.gs(R.string.deletefuturetreatments) + "?", Runnable { + uel.log(Action.DELETE_FUTURE_TREATMENTS, Sources.Treatments) + disposable += repository + .getBolusesDataFromTime(dateUtil.now(), false) + .observeOn(aapsSchedulers.main) + .subscribe { list -> + list.forEach { bolus -> + disposable += repository.runTransactionForResult(InvalidateBolusTransaction(bolus.id)) + .subscribe( + { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bolus $it") } }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating bolus", it) } + ) + } + } + disposable += repository + .getCarbsDataFromTimeNotExpanded(dateUtil.now(), false) + .observeOn(aapsSchedulers.main) + .subscribe { list -> + list.forEach { carb -> + if (carb.duration == 0L) + disposable += repository.runTransactionForResult(InvalidateCarbsTransaction(carb.id)) + .subscribe( + { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") } }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) } + ) + else { + disposable += repository.runTransactionForResult(CutCarbsTransaction(carb.id, dateUtil.now())) + .subscribe( + { result -> + result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") } + result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated (cut end) carbs $it") } + }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) } + ) + } + } + } + disposable += repository + .getBolusCalculatorResultsDataFromTime(dateUtil.now(), false) + .observeOn(aapsSchedulers.main) + .subscribe { list -> + list.forEach { bolusCalc -> + disposable += repository.runTransactionForResult(InvalidateBolusCalculatorResultTransaction(bolusCalc.id)) + .subscribe( + { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bolusCalculatorResult $it") } }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating bolusCalculatorResult", it) } + ) + } + } + }) + } + } + + inner class RemoveActionModeCallback : ActionMode.Callback { + + override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { + mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) + selectedItems = mutableListOf() + mode.title = rh.gs(R.string.count_selected, selectedItems.size) + binding.recyclerview.adapter?.notifyDataSetChanged() + return true + } + + override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false + + override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { + return when (item.itemId) { + R.id.remove_selected -> { + removeSelected() + mode.finish() + true + } + + else -> false + } + } + + override fun onDestroyActionMode(mode: ActionMode?) { + removeActionMode = null + binding.recyclerview.adapter?.notifyDataSetChanged() + } + } + + private fun getConfirmationText(): String { + if (selectedItems.size == 1) { + val mealLink = selectedItems.first() + val bolus = mealLink.bolus + if (bolus != null) + return rh.gs(R.string.configbuilder_insulin) + ": " + + rh.gs(R.string.formatinsulinunits, bolus.amount) + "\n" + + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(bolus.timestamp) + val carbs = mealLink.carbs + if (carbs != null) + return rh.gs(R.string.carbs) + ": " + + rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carbs.amount.toInt()) + "\n" + + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(carbs.timestamp) + } + return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) + } + + fun removeSelected() { + if (selectedItems.size > 0) + activity?.let { activity -> + OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { + selectedItems.forEach { ml -> + ml.bolus?.let { bolus -> uel.log( Action.BOLUS_REMOVED, Sources.Treatments, ValueWithUnit.Timestamp(bolus.timestamp), ValueWithUnit.Insulin(bolus.amount) - //ValueWithUnit.Gram(mealLinkLoaded.carbs.toInt()) ) disposable += repository.runTransactionForResult(InvalidateBolusTransaction(bolus.id)) .subscribe( { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated bolus $it") } }, { aapsLogger.error(LTag.DATABASE, "Error while invalidating bolus", it) } ) - }) - } - } - binding.bolusRemove.paintFlags = binding.bolusRemove.paintFlags or Paint.UNDERLINE_TEXT_FLAG - binding.carbsRemove.setOnClickListener { ml -> - val carb = (ml.tag as MealLink?)?.carbs ?: return@setOnClickListener - activity?.let { activity -> - val text = rh.gs(R.string.carbs) + ": " + - rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carb.amount.toInt()) + "\n" + - rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(carb.timestamp) - OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), text, Runnable { + } + ml.carbs?.let { carb -> uel.log( Action.CARBS_REMOVED, Sources.Treatments, ValueWithUnit.Timestamp(carb.timestamp), @@ -398,11 +497,12 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated carbs $it") } }, { aapsLogger.error(LTag.DATABASE, "Error while invalidating carbs", it) } ) - }) + } } - } - binding.carbsRemove.paintFlags = binding.carbsRemove.paintFlags or Paint.UNDERLINE_TEXT_FLAG + selectedItems = mutableListOf() + }, Runnable { + selectedItems = mutableListOf() + }) } - } } -} \ No newline at end of file +} diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt index 0dca0e416f..59efc40861 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt @@ -1,10 +1,9 @@ package info.nightscout.androidaps.activities.fragments -import android.graphics.Paint import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup +import android.view.* +import android.view.ActionMode +import androidx.appcompat.widget.Toolbar import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment @@ -60,11 +59,14 @@ class TreatmentsCareportalFragment : DaggerFragment() { private val disposable = CompositeDisposable() private val millsToThePast = T.days(30).msecs() + private var selectedItems: MutableList = mutableListOf() + private var showInvalidated = false + private var toolbar: Toolbar? = null + private var removeActionMode: ActionMode? = null private var _binding: TreatmentsCareportalFragmentBinding? = null - // This property is only valid between onCreateView and - // onDestroyView. + // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = @@ -72,46 +74,44 @@ class TreatmentsCareportalFragment : DaggerFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + toolbar = activity?.findViewById(R.id.toolbar) + setHasOptionsMenu(true) binding.recyclerview.setHasFixedSize(true) binding.recyclerview.layoutManager = LinearLayoutManager(view.context) - binding.refreshFromNightscout.setOnClickListener { - activity?.let { activity -> - OKDialog.showConfirmation(activity, rh.gs(R.string.careportal), rh.gs(R.string.refresheventsfromnightscout) + " ?", Runnable { - uel.log(Action.CAREPORTAL_NS_REFRESH, Sources.Treatments) - disposable += Completable.fromAction { repository.deleteAllTherapyEventsEntries() } - .subscribeOn(aapsSchedulers.io) - .subscribeBy( - onError = { aapsLogger.error("Error removing entries", it) }, - onComplete = { rxBus.send(EventTherapyEventChange()) } - ) - rxBus.send(EventNSClientRestart()) - }) - } - } - binding.removeAndroidapsStartedEvents.setOnClickListener { - activity?.let { activity -> - OKDialog.showConfirmation(activity, rh.gs(R.string.careportal), rh.gs(R.string.careportal_removestartedevents), Runnable { - uel.log(Action.RESTART_EVENTS_REMOVED, Sources.Treatments) - repository.runTransactionForResult(InvalidateAAPSStartedTherapyEventTransaction(rh.gs(R.string.androidaps_start))) - .subscribe( - { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated therapy event $it") } }, - { aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) } - ) - }, null) - } - } + } - val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_therapy_events, false) || !buildHelper.isEngineeringMode() - if (nsUploadOnly) binding.refreshFromNightscout.visibility = View.GONE - binding.showInvalidated.setOnCheckedChangeListener { _, _ -> - rxBus.send(EventTreatmentUpdateGui()) + private fun refreshFromNightscout() { + activity?.let { activity -> + OKDialog.showConfirmation(activity, rh.gs(R.string.careportal), rh.gs(R.string.refresheventsfromnightscout) + " ?", Runnable { + uel.log(Action.CAREPORTAL_NS_REFRESH, Sources.Treatments) + disposable += Completable.fromAction { repository.deleteAllTherapyEventsEntries() } + .subscribeOn(aapsSchedulers.io) + .subscribeBy( + onError = { aapsLogger.error("Error removing entries", it) }, + onComplete = { rxBus.send(EventTherapyEventChange()) } + ) + rxBus.send(EventNSClientRestart()) + }) + } + } + + private fun removeStartedEvents() { + activity?.let { activity -> + OKDialog.showConfirmation(activity, rh.gs(R.string.careportal), rh.gs(R.string.careportal_removestartedevents), Runnable { + uel.log(Action.RESTART_EVENTS_REMOVED, Sources.Treatments) + disposable += repository.runTransactionForResult(InvalidateAAPSStartedTherapyEventTransaction(rh.gs(R.string.androidaps_start))) + .subscribe( + { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated therapy event $it") } }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) } + ) + }) } } fun swapAdapter() { val now = System.currentTimeMillis() disposable += - if (binding.showInvalidated.isChecked) + if (showInvalidated) repository .getTherapyEventDataIncludingInvalidFromTime(now - millsToThePast, false) .observeOn(aapsSchedulers.main) @@ -148,6 +148,7 @@ class TreatmentsCareportalFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() + removeActionMode?.let { it.finish() } binding.recyclerview.adapter = null // avoid leaks _binding = null } @@ -170,42 +171,135 @@ class TreatmentsCareportalFragment : DaggerFragment() { holder.binding.duration.text = if (therapyEvent.duration == 0L) "" else dateUtil.niceTimeScalar(therapyEvent.duration, rh) holder.binding.note.text = therapyEvent.note holder.binding.type.text = translator.translate(therapyEvent.type) - holder.binding.remove.tag = therapyEvent + holder.binding.cbRemove.visibility = (therapyEvent.isValid && (removeActionMode != null)).toVisibility() + holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> + if (value) { + selectedItems.add(therapyEvent) + } else { + selectedItems.remove(therapyEvent) + } + removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size) + } val nextTimestamp = if (therapyList.size != position + 1) therapyList[position + 1].timestamp else 0L holder.binding.delimiter.visibility = dateUtil.isSameDay(therapyEvent.timestamp, nextTimestamp).toVisibility() } - override fun getItemCount(): Int { - return therapyList.size - } + override fun getItemCount() = therapyList.size inner class TherapyEventsViewHolder(view: View) : RecyclerView.ViewHolder(view) { val binding = TreatmentsCareportalItemBinding.bind(view) - - init { - binding.remove.setOnClickListener { v: View -> - val therapyEvent = v.tag as TherapyEvent - activity?.let { activity -> - val text = rh.gs(R.string.eventtype) + ": " + translator.translate(therapyEvent.type) + "\n" + - rh.gs(R.string.notes_label) + ": " + (therapyEvent.note - ?: "") + "\n" + - rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(therapyEvent.timestamp) - OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), text, Runnable { - uel.log(Action.CAREPORTAL_REMOVED, Sources.Treatments, therapyEvent.note , - ValueWithUnit.Timestamp(therapyEvent.timestamp), - ValueWithUnit.TherapyEventType(therapyEvent.type)) - disposable += repository.runTransactionForResult(InvalidateTherapyEventTransaction(therapyEvent.id)) - .subscribe( - { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated therapy event $it") } }, - { aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) } - ) - }, null) - } - } - binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG - } } } -} \ No newline at end of file + + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.menu_treatments_careportal, menu) + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onPrepareOptionsMenu(menu: Menu) { + menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated + menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated + val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_therapy_events, false) || !buildHelper.isEngineeringMode() + menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly + + return super.onPrepareOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.nav_remove_items -> { + removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback()) + true + } + + R.id.nav_show_invalidated -> { + showInvalidated = true + rxBus.send(EventTreatmentUpdateGui()) + true + } + + R.id.nav_hide_invalidated -> { + showInvalidated = false + rxBus.send(EventTreatmentUpdateGui()) + true + } + + R.id.nav_remove_started_events -> { + removeStartedEvents() + true + } + + R.id.nav_refresh_ns -> { + refreshFromNightscout() + true + } + + else -> false + } + } + + inner class RemoveActionModeCallback : ActionMode.Callback { + + override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { + mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) + selectedItems = mutableListOf() + mode.title = rh.gs(R.string.count_selected, selectedItems.size) + binding.recyclerview.adapter?.notifyDataSetChanged() + return true + } + + override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false + + override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { + return when (item.itemId) { + R.id.remove_selected -> { + removeSelected() + mode.finish() + true + } + + else -> false + } + } + + override fun onDestroyActionMode(mode: ActionMode?) { + removeActionMode = null + binding.recyclerview.adapter?.notifyDataSetChanged() + } + } + + private fun getConfirmationText(): String { + if (selectedItems.size == 1) { + val therapyEvent = selectedItems.first() + return rh.gs(R.string.eventtype) + ": " + translator.translate(therapyEvent.type) + "\n" + + rh.gs(R.string.notes_label) + ": " + (therapyEvent.note ?: "") + "\n" + + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(therapyEvent.timestamp) + } + return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) + } + + private fun removeSelected() { + if (selectedItems.size > 0) + activity?.let { activity -> + OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { + selectedItems.forEach { therapyEvent -> + uel.log( + Action.CAREPORTAL_REMOVED, Sources.Treatments, therapyEvent.note, + ValueWithUnit.Timestamp(therapyEvent.timestamp), + ValueWithUnit.TherapyEventType(therapyEvent.type) + ) + disposable += repository.runTransactionForResult(InvalidateTherapyEventTransaction(therapyEvent.id)) + .subscribe( + { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated therapy event $it") } }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) } + ) + } + + }) + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt index bdd0e4f424..af1499bf76 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt @@ -1,12 +1,10 @@ package info.nightscout.androidaps.activities.fragments import android.annotation.SuppressLint -import android.content.DialogInterface -import android.graphics.Paint import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup +import android.view.* +import android.view.ActionMode +import androidx.appcompat.widget.Toolbar import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment @@ -27,16 +25,17 @@ import info.nightscout.androidaps.extensions.toVisibility import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.shared.logging.AAPSLogger -import info.nightscout.shared.logging.LTag import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.activities.fragments.TreatmentsExtendedBolusesFragment.RecyclerViewAdapter.ExtendedBolusesViewHolder +import info.nightscout.androidaps.events.EventTreatmentUpdateGui import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers +import info.nightscout.shared.logging.LTag import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign import java.util.concurrent.TimeUnit @@ -61,22 +60,28 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { private var _binding: TreatmentsExtendedbolusFragmentBinding? = null - // This property is only valid between onCreateView and - // onDestroyView. + // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle?): View = + private var selectedItems: MutableList = mutableListOf() + private var showInvalidated = false + private var removeActionMode: ActionMode? = null + private var toolbar: Toolbar? = null + // val TAG = "TreatmentMenu" + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = TreatmentsExtendedbolusFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + setHasOptionsMenu(true) + toolbar = activity?.findViewById(R.id.toolbar) binding.recyclerview.setHasFixedSize(true) binding.recyclerview.layoutManager = LinearLayoutManager(view.context) } fun swapAdapter() { val now = System.currentTimeMillis() - if (binding.showInvalidated.isChecked) + disposable += if (showInvalidated) repository .getExtendedBolusDataIncludingInvalidFromTime(now - millsToThePast, false) .observeOn(aapsSchedulers.main) @@ -109,6 +114,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() + removeActionMode?.let { it.finish() } binding.recyclerview.adapter = null // avoid leaks _binding = null } @@ -125,7 +131,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { holder.binding.ns.visibility = (extendedBolus.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.ph.visibility = (extendedBolus.interfaceIDs.pumpId != null).toVisibility() holder.binding.invalid.visibility = extendedBolus.isValid.not().toVisibility() - val sameDayPrevious = position > 0 && dateUtil.isSameDay(extendedBolus.timestamp, extendedBolusList[position-1].timestamp) + val sameDayPrevious = position > 0 && dateUtil.isSameDay(extendedBolus.timestamp, extendedBolusList[position - 1].timestamp) holder.binding.date.visibility = sameDayPrevious.not().toVisibility() holder.binding.date.text = dateUtil.dateString(extendedBolus.timestamp) @SuppressLint("SetTextI18n") @@ -143,41 +149,119 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { holder.binding.iob.text = rh.gs(R.string.formatinsulinunits, iob.iob) holder.binding.ratio.text = rh.gs(R.string.pump_basebasalrate, extendedBolus.rate) if (iob.iob != 0.0) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.insulin.currentTextColor) - holder.binding.remove.tag = extendedBolus + holder.binding.cbRemove.visibility = (extendedBolus.isValid && (removeActionMode != null)).toVisibility() + holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> + if (value) { + selectedItems.add(extendedBolus) + } else { + selectedItems.remove(extendedBolus) + } + removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size) + } val nextTimestamp = if (extendedBolusList.size != position + 1) extendedBolusList[position + 1].timestamp else 0L holder.binding.delimiter.visibility = dateUtil.isSameDay(extendedBolus.timestamp, nextTimestamp).toVisibility() } - override fun getItemCount(): Int = extendedBolusList.size + override fun getItemCount() = extendedBolusList.size inner class ExtendedBolusesViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val binding = TreatmentsExtendedbolusItemBinding.bind(itemView) - - init { - binding.remove.setOnClickListener { v: View -> - val extendedBolus = v.tag as ExtendedBolus - context?.let { context -> - OKDialog.showConfirmation(context, rh.gs(R.string.removerecord), - """ - ${rh.gs(R.string.extended_bolus)} - ${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(extendedBolus.timestamp)} - """.trimIndent(), { _: DialogInterface, _: Int -> - uel.log(Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments, - ValueWithUnit.Timestamp(extendedBolus.timestamp), - ValueWithUnit.Insulin(extendedBolus.amount), - ValueWithUnit.UnitPerHour(extendedBolus.rate), - ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt())) - disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id)) - .subscribe( - { aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") }, - { aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) }) - }, null) - } - } - binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG - } } } -} \ No newline at end of file + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.menu_treatments_extended_bolus, menu) + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onPrepareOptionsMenu(menu: Menu) { + menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated + menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated + + return super.onPrepareOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.nav_remove_items -> { + removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback()) + true + } + + R.id.nav_show_invalidated -> { + showInvalidated = true + rxBus.send(EventTreatmentUpdateGui()) + true + } + + R.id.nav_hide_invalidated -> { + showInvalidated = false + rxBus.send(EventTreatmentUpdateGui()) + true + } + + else -> false + } + } + + inner class RemoveActionModeCallback : ActionMode.Callback { + + override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { + mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) + selectedItems = mutableListOf() + mode.title = rh.gs(R.string.count_selected, selectedItems.size) + binding.recyclerview.adapter?.notifyDataSetChanged() + return true + } + + override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false + + override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { + return when (item.itemId) { + R.id.remove_selected -> { + removeSelected() + mode.finish() + true + } + + else -> false + } + } + + override fun onDestroyActionMode(mode: ActionMode?) { + removeActionMode = null + binding.recyclerview.adapter?.notifyDataSetChanged() + } + } + + private fun getConfirmationText(): String { + if (selectedItems.size == 1) { + return rh.gs(R.string.extended_bolus) + "\n" + + "${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(selectedItems.first().timestamp)}" + } + return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) + } + + private fun removeSelected() { + if (selectedItems.size > 0) + activity?.let { activity -> + OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { + selectedItems.forEach { extendedBolus -> + uel.log( + Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments, + ValueWithUnit.Timestamp(extendedBolus.timestamp), + ValueWithUnit.Insulin(extendedBolus.amount), + ValueWithUnit.UnitPerHour(extendedBolus.rate), + ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt()) + ) + disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id)) + .subscribe( + { aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) }) + } + }) + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt index 91b46228be..3d2af3afd0 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt @@ -2,9 +2,9 @@ package info.nightscout.androidaps.activities.fragments import android.graphics.Paint import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup +import android.view.* +import android.view.ActionMode +import androidx.appcompat.widget.Toolbar import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment @@ -65,9 +65,12 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { private val disposable = CompositeDisposable() private val millsToThePast = T.days(30).msecs() + private var selectedItems: MutableList = mutableListOf() + private var showInvalidated = false + private var removeActionMode: ActionMode? = null + private var toolbar: Toolbar? = null - // This property is only valid between onCreateView and - // onDestroyView. + // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = @@ -75,36 +78,34 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + setHasOptionsMenu(true) + toolbar = activity?.findViewById(R.id.toolbar) binding.recyclerview.setHasFixedSize(true) binding.recyclerview.layoutManager = LinearLayoutManager(view.context) + } - binding.refreshFromNightscout.setOnClickListener { - activity?.let { activity -> - OKDialog.showConfirmation(activity, rh.gs(R.string.refresheventsfromnightscout) + "?") { - uel.log(Action.TREATMENTS_NS_REFRESH, Sources.Treatments) - disposable += - Completable.fromAction { - repository.deleteAllEffectiveProfileSwitches() - repository.deleteAllProfileSwitches() - } - .subscribeOn(aapsSchedulers.io) - .observeOn(aapsSchedulers.main) - .subscribeBy( - onError = { aapsLogger.error("Error removing entries", it) }, - onComplete = { - rxBus.send(EventProfileSwitchChanged()) - rxBus.send(EventEffectiveProfileSwitchChanged(0L)) - rxBus.send(EventNewHistoryData(0, false)) - } - ) - rxBus.send(EventNSClientRestart()) - } + private fun refreshFromNightscout() { + activity?.let { activity -> + OKDialog.showConfirmation(activity, rh.gs(R.string.refresheventsfromnightscout) + "?") { + uel.log(Action.TREATMENTS_NS_REFRESH, Sources.Treatments) + disposable += + Completable.fromAction { + repository.deleteAllEffectiveProfileSwitches() + repository.deleteAllProfileSwitches() + } + .subscribeOn(aapsSchedulers.io) + .observeOn(aapsSchedulers.main) + .subscribeBy( + onError = { aapsLogger.error("Error removing entries", it) }, + onComplete = { + rxBus.send(EventProfileSwitchChanged()) + rxBus.send(EventEffectiveProfileSwitchChanged(0L)) + rxBus.send(EventNewHistoryData(0, false)) + } + ) + rxBus.send(EventNSClientRestart()) } } - if (!sp.getBoolean(R.string.key_ns_receive_profile_switch, false) || !buildHelper.isEngineeringMode()) binding.refreshFromNightscout.visibility = View.GONE - binding.showInvalidated.setOnCheckedChangeListener { _, _ -> - rxBus.send(EventTreatmentUpdateGui()) - } } private fun profileSwitchWithInvalid(now: Long) = repository @@ -126,23 +127,23 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { fun swapAdapter() { val now = System.currentTimeMillis() - if (binding.showInvalidated.isChecked) - disposable += profileSwitchWithInvalid(now) - .zipWith(effectiveProfileSwitchWithInvalid(now)) { first, second -> first + second } - .map { ml -> ml.sortedByDescending { it.timestamp } } - .observeOn(aapsSchedulers.main) - .subscribe { list -> - binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true) - } - else - disposable += profileSwitches(now) - .zipWith(effectiveProfileSwitches(now)) { first, second -> first + second } - .map { ml -> ml.sortedByDescending { it.timestamp } } - .observeOn(aapsSchedulers.main) - .subscribe { list -> - binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true) - } - + disposable += + if (showInvalidated) + profileSwitchWithInvalid(now) + .zipWith(effectiveProfileSwitchWithInvalid(now)) { first, second -> first + second } + .map { ml -> ml.sortedByDescending { it.timestamp } } + .observeOn(aapsSchedulers.main) + .subscribe { list -> + binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true) + } + else + profileSwitches(now) + .zipWith(effectiveProfileSwitches(now)) { first, second -> first + second } + .map { ml -> ml.sortedByDescending { it.timestamp } } + .observeOn(aapsSchedulers.main) + .subscribe { list -> + binding.recyclerview.swapAdapter(RecyclerProfileViewAdapter(list), true) + } } @Synchronized @@ -168,6 +169,7 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() + removeActionMode?.let { it.finish() } binding.recyclerview.adapter = null // avoid leaks _binding = null } @@ -189,13 +191,20 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { holder.binding.name.text = if (profileSwitch is ProfileSealed.PS) profileSwitch.value.getCustomizedName() else if (profileSwitch is ProfileSealed.EPS) profileSwitch.value.originalCustomizedName else "" if (profileSwitch.isInProgress(dateUtil)) holder.binding.date.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.date.setTextColor(holder.binding.duration.currentTextColor) - holder.binding.remove.tag = profileSwitch holder.binding.clone.tag = profileSwitch holder.binding.name.tag = profileSwitch holder.binding.date.tag = profileSwitch holder.binding.invalid.visibility = profileSwitch.isValid.not().toVisibility() holder.binding.duration.visibility = (profileSwitch.duration != 0L && profileSwitch.duration != null).toVisibility() - holder.binding.remove.visibility = (profileSwitch is ProfileSealed.PS).toVisibility() + holder.binding.cbRemove.visibility = (removeActionMode != null && profileSwitch is ProfileSealed.PS).toVisibility() + holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> + if (value) { + selectedItems.add(profileSwitch) + } else { + selectedItems.remove(profileSwitch) + } + removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size) + } holder.binding.clone.visibility = (profileSwitch is ProfileSealed.PS).toVisibility() holder.binding.spacer.visibility = (profileSwitch is ProfileSealed.PS).toVisibility() holder.binding.root.setBackgroundColor(rh.gc(if (profileSwitch is ProfileSealed.PS) R.color.defaultbackground else R.color.list_delimiter)) @@ -203,47 +212,39 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { holder.binding.delimiter.visibility = dateUtil.isSameDay(profileSwitch.timestamp, nextTimestamp).toVisibility() } - override fun getItemCount(): Int { - return profileSwitchList.size - } + override fun getItemCount() = profileSwitchList.size inner class ProfileSwitchViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) { val binding = TreatmentsProfileswitchItemBinding.bind(itemView) init { - binding.remove.setOnClickListener { view -> - val profileSwitch = view.tag as ProfileSealed.PS - activity?.let { activity -> - OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), - rh.gs(R.string.careportal_profileswitch) + ": " + profileSwitch.profileName + - "\n" + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(profileSwitch.timestamp), Runnable { - uel.log(Action.PROFILE_SWITCH_REMOVED, Sources.Treatments, profileSwitch.profileName, - ValueWithUnit.Timestamp(profileSwitch.timestamp)) - disposable += repository.runTransactionForResult(InvalidateProfileSwitchTransaction(profileSwitch.id)) - .subscribe( - { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated ProfileSwitch $it") } }, - { aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it) } - ) - }) - } - } binding.clone.setOnClickListener { activity?.let { activity -> val profileSwitch = (it.tag as ProfileSealed.PS).value val profileSealed = it.tag as ProfileSealed - OKDialog.showConfirmation(activity, rh.gs(R.string.careportal_profileswitch), rh.gs(R.string.copytolocalprofile) + "\n" + profileSwitch.getCustomizedName() + "\n" + dateUtil.dateAndTimeString(profileSwitch.timestamp), Runnable { - uel.log(Action.PROFILE_SWITCH_CLONED, Sources.Treatments, - profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_"), - ValueWithUnit.Timestamp(profileSwitch.timestamp), - ValueWithUnit.SimpleString(profileSwitch.profileName)) - val nonCustomized = profileSealed.convertToNonCustomizedProfile(dateUtil) - localProfilePlugin.addProfile(localProfilePlugin.copyFrom(nonCustomized, profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_"))) - rxBus.send(EventLocalProfileChanged()) - }) + OKDialog.showConfirmation( + activity, + rh.gs(R.string.careportal_profileswitch), + rh.gs(R.string.copytolocalprofile) + "\n" + profileSwitch.getCustomizedName() + "\n" + dateUtil.dateAndTimeString(profileSwitch.timestamp), + Runnable { + uel.log( + Action.PROFILE_SWITCH_CLONED, Sources.Treatments, + profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_"), + ValueWithUnit.Timestamp(profileSwitch.timestamp), + ValueWithUnit.SimpleString(profileSwitch.profileName) + ) + val nonCustomized = profileSealed.convertToNonCustomizedProfile(dateUtil) + localProfilePlugin.addProfile( + localProfilePlugin.copyFrom( + nonCustomized, + profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_") + ) + ) + rxBus.send(EventLocalProfileChanged()) + }) } } - binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG binding.clone.paintFlags = binding.clone.paintFlags or Paint.UNDERLINE_TEXT_FLAG binding.name.setOnClickListener { ProfileViewerDialog().also { pvd -> @@ -266,4 +267,103 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { } } } -} \ No newline at end of file + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.menu_treatments_profile_switch, menu) + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onPrepareOptionsMenu(menu: Menu) { + menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated + menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated + val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_profile_switch, false) || !buildHelper.isEngineeringMode() + menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly + + return super.onPrepareOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.nav_remove_items -> { + removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback()) + true + } + + R.id.nav_show_invalidated -> { + showInvalidated = true + rxBus.send(EventTreatmentUpdateGui()) + true + } + + R.id.nav_hide_invalidated -> { + showInvalidated = false + rxBus.send(EventTreatmentUpdateGui()) + true + } + + R.id.nav_refresh_ns -> { + refreshFromNightscout() + true + } + + else -> false + } + } + + inner class RemoveActionModeCallback : ActionMode.Callback { + + override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { + mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) + selectedItems = mutableListOf() + mode.title = rh.gs(R.string.count_selected, selectedItems.size) + binding.recyclerview.adapter?.notifyDataSetChanged() + return true + } + + override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false + + override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { + return when (item.itemId) { + R.id.remove_selected -> { + removeSelected() + mode.finish() + true + } + + else -> false + } + } + + override fun onDestroyActionMode(mode: ActionMode?) { + removeActionMode = null + binding.recyclerview.adapter?.notifyDataSetChanged() + } + } + + private fun getConfirmationText(): String { + if (selectedItems.size == 1) { + val profileSwitch = selectedItems.first() + return rh.gs(R.string.careportal_profileswitch) + ": " + profileSwitch.profileName + "\n" + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(profileSwitch.timestamp) + } + return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) + } + + private fun removeSelected() { + if (selectedItems.size > 0) + activity?.let { activity -> + OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { + selectedItems.forEach { profileSwitch -> + uel.log( + Action.PROFILE_SWITCH_REMOVED, Sources.Treatments, profileSwitch.profileName, + ValueWithUnit.Timestamp(profileSwitch.timestamp) + ) + disposable += repository.runTransactionForResult(InvalidateProfileSwitchTransaction(profileSwitch.id)) + .subscribe( + { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated ProfileSwitch $it") } }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it) } + ) + } + }) + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt index c408fd4299..479f0008de 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt @@ -1,12 +1,9 @@ package info.nightscout.androidaps.activities.fragments import android.annotation.SuppressLint -import android.content.DialogInterface -import android.graphics.Paint import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup +import android.view.* +import androidx.appcompat.widget.Toolbar import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment @@ -30,6 +27,8 @@ import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientRestart import info.nightscout.androidaps.events.EventTreatmentUpdateGui import info.nightscout.androidaps.activities.fragments.TreatmentsTempTargetFragment.RecyclerViewAdapter.TempTargetsViewHolder +import info.nightscout.androidaps.events.EventEffectiveProfileSwitchChanged +import info.nightscout.androidaps.events.EventProfileSwitchChanged import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T @@ -40,6 +39,7 @@ import info.nightscout.androidaps.extensions.friendlyDescription import info.nightscout.androidaps.extensions.highValueToUnitsToString import info.nightscout.androidaps.extensions.lowValueToUnitsToString import info.nightscout.androidaps.extensions.toVisibility +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventNewHistoryData import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.shared.sharedPreferences.SP @@ -68,11 +68,14 @@ class TreatmentsTempTargetFragment : DaggerFragment() { private val disposable = CompositeDisposable() private val millsToThePast = T.days(30).msecs() + private var selectedItems: MutableList = mutableListOf() + private var showInvalidated = false + private var toolbar: Toolbar? = null + private var removeActionMode: ActionMode? = null private var _binding: TreatmentsTemptargetFragmentBinding? = null - // This property is only valid between onCreateView and - // onDestroyView. + // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = @@ -80,42 +83,48 @@ class TreatmentsTempTargetFragment : DaggerFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { binding.recyclerview.setHasFixedSize(true) + toolbar = activity?.findViewById(R.id.toolbar) + setHasOptionsMenu(true) binding.recyclerview.layoutManager = LinearLayoutManager(view.context) - binding.refreshFromNightscout.setOnClickListener { - context?.let { context -> - OKDialog.showConfirmation(context, rh.gs(R.string.refresheventsfromnightscout) + " ?", { - uel.log(Action.TT_NS_REFRESH, Sources.Treatments) - disposable += Completable.fromAction { repository.deleteAllTempTargetEntries() } + } + + private fun refreshFromNightscout() { + activity?.let { activity -> + OKDialog.showConfirmation(activity, rh.gs(R.string.refresheventsfromnightscout) + "?") { + uel.log(Action.TREATMENTS_NS_REFRESH, Sources.Treatments) + disposable += + Completable.fromAction { + repository.deleteAllEffectiveProfileSwitches() + repository.deleteAllProfileSwitches() + } .subscribeOn(aapsSchedulers.io) .observeOn(aapsSchedulers.main) .subscribeBy( onError = { aapsLogger.error("Error removing entries", it) }, - onComplete = { rxBus.send(EventTempTargetChange()) } + onComplete = { + rxBus.send(EventProfileSwitchChanged()) + rxBus.send(EventEffectiveProfileSwitchChanged(0L)) + rxBus.send(EventNewHistoryData(0, false)) + } ) - - rxBus.send(EventNSClientRestart()) - }) + rxBus.send(EventNSClientRestart()) } } - val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_temp_target, false) || !buildHelper.isEngineeringMode() - if (nsUploadOnly) binding.refreshFromNightscout.visibility = View.INVISIBLE - binding.showInvalidated.setOnCheckedChangeListener { _, _ -> - rxBus.send(EventTreatmentUpdateGui()) - } } fun swapAdapter() { val now = System.currentTimeMillis() - if (binding.showInvalidated.isChecked) - repository - .getTemporaryTargetDataIncludingInvalidFromTime(now - millsToThePast, false) - .observeOn(aapsSchedulers.main) - .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } - else - repository - .getTemporaryTargetDataFromTime(now - millsToThePast, false) - .observeOn(aapsSchedulers.main) - .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } + disposable += + if (showInvalidated) + repository + .getTemporaryTargetDataIncludingInvalidFromTime(now - millsToThePast, false) + .observeOn(aapsSchedulers.main) + .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } + else + repository + .getTemporaryTargetDataFromTime(now - millsToThePast, false) + .observeOn(aapsSchedulers.main) + .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } } @Synchronized @@ -145,6 +154,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() + removeActionMode?.let { it.finish() } binding.recyclerview.adapter = null // avoid leaks _binding = null } @@ -163,8 +173,16 @@ class TreatmentsTempTargetFragment : DaggerFragment() { val tempTarget = tempTargetList[position] holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility() - holder.binding.remove.visibility = tempTarget.isValid.toVisibility() - val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempTarget.timestamp, tempTargetList[position-1].timestamp) + holder.binding.cbRemove.visibility = (tempTarget.isValid && (removeActionMode != null)).toVisibility() + holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> + if (value) { + selectedItems.add(tempTarget) + } else { + selectedItems.remove(tempTarget) + } + removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size) + } + val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempTarget.timestamp, tempTargetList[position - 1].timestamp) holder.binding.date.visibility = sameDayPrevious.not().toVisibility() holder.binding.date.text = dateUtil.dateString(tempTarget.timestamp) holder.binding.time.text = dateUtil.timeRangeString(tempTarget.timestamp, tempTarget.end) @@ -177,43 +195,123 @@ class TreatmentsTempTargetFragment : DaggerFragment() { tempTarget.id == currentlyActiveTarget?.id -> rh.gc(R.color.colorActive) tempTarget.timestamp > dateUtil.now() -> rh.gc(R.color.colorScheduled) else -> holder.binding.reasonColon.currentTextColor - }) - holder.binding.remove.tag = tempTarget + } + ) val nextTimestamp = if (tempTargetList.size != position + 1) tempTargetList[position + 1].timestamp else 0L holder.binding.delimiter.visibility = dateUtil.isSameDay(tempTarget.timestamp, nextTimestamp).toVisibility() } - override fun getItemCount(): Int = tempTargetList.size + override fun getItemCount() = tempTargetList.size inner class TempTargetsViewHolder(view: View) : RecyclerView.ViewHolder(view) { val binding = TreatmentsTemptargetItemBinding.bind(view) - init { - binding.remove.setOnClickListener { v: View -> - val tempTarget = v.tag as TemporaryTarget - context?.let { context -> - OKDialog.showConfirmation(context, rh.gs(R.string.removerecord), - """ - ${rh.gs(R.string.careportal_temporarytarget)}: ${tempTarget.friendlyDescription(profileFunction.getUnits(), rh)} - ${dateUtil.dateAndTimeString(tempTarget.timestamp)} - """.trimIndent(), - { _: DialogInterface?, _: Int -> - uel.log(Action.TT_REMOVED, Sources.Treatments, - ValueWithUnit.Timestamp(tempTarget.timestamp), - ValueWithUnit.TherapyEventTTReason(tempTarget.reason), - ValueWithUnit.Mgdl(tempTarget.lowTarget), - ValueWithUnit.Mgdl(tempTarget.highTarget).takeIf { tempTarget.lowTarget != tempTarget.highTarget }, - ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tempTarget.duration).toInt())) - disposable += repository.runTransactionForResult(InvalidateTemporaryTargetTransaction(tempTarget.id)) - .subscribe( - { aapsLogger.debug(LTag.DATABASE, "Removed temp target $tempTarget") }, - { aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary target", it) }) - }, null) - } - } - binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG - } } } -} \ No newline at end of file + + private fun removeSelected() { + // TODO check if item should not be delete val profile = profileFunction.getProfile(dateUtil.now()) == null + if (selectedItems.size > 0) + activity?.let { activity -> + OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { + selectedItems.forEach { tempTarget -> + uel.log( + Action.TT_REMOVED, Sources.Treatments, + ValueWithUnit.Timestamp(tempTarget.timestamp), + ValueWithUnit.TherapyEventTTReason(tempTarget.reason), + ValueWithUnit.Mgdl(tempTarget.lowTarget), + ValueWithUnit.Mgdl(tempTarget.highTarget).takeIf { tempTarget.lowTarget != tempTarget.highTarget }, + ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(tempTarget.duration).toInt()) + ) + disposable += repository.runTransactionForResult(InvalidateTemporaryTargetTransaction(tempTarget.id)) + .subscribe( + { aapsLogger.debug(LTag.DATABASE, "Removed temp target $tempTarget") }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary target", it) }) + } + }) + } + } + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.menu_treatments_temp_target, menu) + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onPrepareOptionsMenu(menu: Menu) { + menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated + menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated + val nsUploadOnly = !sp.getBoolean(R.string.key_ns_receive_temp_target, false) || !buildHelper.isEngineeringMode() + menu.findItem(R.id.nav_refresh_ns)?.isVisible = !nsUploadOnly + + return super.onPrepareOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.nav_remove_items -> { + removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback()) + true + } + + R.id.nav_show_invalidated -> { + showInvalidated = true + rxBus.send(EventTreatmentUpdateGui()) + true + } + + R.id.nav_hide_invalidated -> { + showInvalidated = false + rxBus.send(EventTreatmentUpdateGui()) + true + } + + R.id.nav_refresh_ns -> { + refreshFromNightscout() + true + } + + else -> false + } + } + + inner class RemoveActionModeCallback : ActionMode.Callback { + + override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { + mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) + selectedItems = mutableListOf() + mode.title = rh.gs(R.string.count_selected, selectedItems.size) + binding.recyclerview.adapter?.notifyDataSetChanged() + return true + } + + override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false + + override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { + return when (item.itemId) { + R.id.remove_selected -> { + removeSelected() + mode.finish() + true + } + + else -> false + } + } + + override fun onDestroyActionMode(mode: ActionMode?) { + removeActionMode = null + binding.recyclerview.adapter?.notifyDataSetChanged() + } + } + + private fun getConfirmationText(): String { + if (selectedItems.size == 1) { + val tempTarget = selectedItems.first() + return "${rh.gs(R.string.careportal_temporarytarget)}: ${tempTarget.friendlyDescription(profileFunction.getUnits(), rh)}\n" + + dateUtil.dateAndTimeString(tempTarget.timestamp) + } + return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt index 6d4c536236..4e166fc46f 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt @@ -1,11 +1,8 @@ package info.nightscout.androidaps.activities.fragments -import android.content.DialogInterface -import android.graphics.Paint import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup +import android.view.* +import androidx.appcompat.widget.Toolbar import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment @@ -36,6 +33,7 @@ import info.nightscout.shared.logging.LTag import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.activities.fragments.TreatmentsTemporaryBasalsFragment.RecyclerViewAdapter.TempBasalsViewHolder +import info.nightscout.androidaps.events.EventTreatmentUpdateGui import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.T @@ -66,9 +64,12 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { private var _binding: TreatmentsTempbasalsFragmentBinding? = null private val millsToThePast = T.days(30).msecs() + private var selectedItems: MutableList = mutableListOf() + private var showInvalidated = false + private var toolbar: Toolbar? = null + private var removeActionMode: ActionMode? = null - // This property is only valid between onCreateView and - // onDestroyView. + // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = @@ -76,6 +77,8 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + toolbar = activity?.findViewById(R.id.toolbar) + setHasOptionsMenu(true) binding.recyclerview.setHasFixedSize(true) binding.recyclerview.layoutManager = LinearLayoutManager(view.context) } @@ -98,7 +101,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { val now = System.currentTimeMillis() disposable += if (activePlugin.activePump.isFakingTempsByExtendedBoluses) { - if (binding.showInvalidated.isChecked) + if (showInvalidated) tempBasalsWithInvalid(now) .zipWith(extendedBolusesWithInvalid(now)) { first, second -> first + second } .map { list -> list.filterNotNull() } @@ -113,7 +116,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { .observeOn(aapsSchedulers.main) .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } } else { - if (binding.showInvalidated.isChecked) + if (showInvalidated) tempBasalsWithInvalid(now) .observeOn(aapsSchedulers.main) .subscribe { list -> binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } @@ -150,6 +153,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { @Synchronized override fun onDestroyView() { super.onDestroyView() + removeActionMode?.let { it.finish() } binding.recyclerview.adapter = null // avoid leaks _binding = null } @@ -164,7 +168,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { holder.binding.ns.visibility = (tempBasal.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.invalid.visibility = tempBasal.isValid.not().toVisibility() holder.binding.ph.visibility = (tempBasal.interfaceIDs.pumpId != null).toVisibility() - val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempBasal.timestamp, tempBasalList[position-1].timestamp) + val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempBasal.timestamp, tempBasalList[position - 1].timestamp) holder.binding.date.visibility = sameDayPrevious.not().toVisibility() holder.binding.date.text = dateUtil.dateString(tempBasal.timestamp) if (tempBasal.isInProgress) { @@ -187,62 +191,144 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { holder.binding.emulatedSuspendFlag.visibility = (tempBasal.type == TemporaryBasal.Type.EMULATED_PUMP_SUSPEND).toVisibility() holder.binding.superBolusFlag.visibility = (tempBasal.type == TemporaryBasal.Type.SUPERBOLUS).toVisibility() if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor) - holder.binding.remove.tag = tempBasal - + holder.binding.cbRemove.visibility = (tempBasal.isValid && (removeActionMode != null)).toVisibility() + holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> + if (value) { + selectedItems.add(tempBasal) + } else { + selectedItems.remove(tempBasal) + } + removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size) + } val nextTimestamp = if (tempBasalList.size != position + 1) tempBasalList[position + 1].timestamp else 0L holder.binding.delimiter.visibility = dateUtil.isSameDay(tempBasal.timestamp, nextTimestamp).toVisibility() } - override fun getItemCount(): Int = tempBasalList.size + override fun getItemCount() = tempBasalList.size inner class TempBasalsViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val binding = TreatmentsTempbasalsItemBinding.bind(itemView) - init { - binding.remove.setOnClickListener { v: View -> - val tempBasal = v.tag as TemporaryBasal - var extendedBolus: ExtendedBolus? = null - val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED - if (isFakeExtended) { - val eb = repository.getExtendedBolusActiveAt(tempBasal.timestamp).blockingGet() - extendedBolus = if (eb is ValueWrapper.Existing) eb.value else null - } - val profile = profileFunction.getProfile(dateUtil.now()) - ?: return@setOnClickListener - context?.let { - OKDialog.showConfirmation(it, rh.gs(R.string.removerecord), - """ - ${if (isFakeExtended) rh.gs(R.string.extended_bolus) else rh.gs(R.string.tempbasal_label)}: ${tempBasal.toStringFull(profile, dateUtil)} - ${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(tempBasal.timestamp)} - """.trimIndent(), - { _: DialogInterface?, _: Int -> - if (isFakeExtended && extendedBolus != null) { - uel.log(Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments, - ValueWithUnit.Timestamp(extendedBolus.timestamp), - ValueWithUnit.Insulin(extendedBolus.amount), - ValueWithUnit.UnitPerHour(extendedBolus.rate), - ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt())) - disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id)) - .subscribe( - { aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") }, - { aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) }) - } else if (!isFakeExtended) { - uel.log(Action.TEMP_BASAL_REMOVED, Sources.Treatments, - ValueWithUnit.Timestamp(tempBasal.timestamp), - if (tempBasal.isAbsolute) ValueWithUnit.UnitPerHour(tempBasal.rate) else ValueWithUnit.Percent(tempBasal.rate.toInt()), - ValueWithUnit.Minute(T.msecs(tempBasal.duration).mins().toInt())) - disposable += repository.runTransactionForResult(InvalidateTemporaryBasalTransaction(tempBasal.id)) - .subscribe( - { aapsLogger.debug(LTag.DATABASE, "Removed temporary basal $tempBasal") }, - { aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) }) - } - }, null) - } - } - binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG - } } } -} \ No newline at end of file + + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.menu_treatments_temp_basal, menu) + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onPrepareOptionsMenu(menu: Menu) { + menu.findItem(R.id.nav_hide_invalidated)?.isVisible = showInvalidated + menu.findItem(R.id.nav_show_invalidated)?.isVisible = !showInvalidated + + return super.onPrepareOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.nav_remove_items -> { + removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback()) + true + } + + R.id.nav_show_invalidated -> { + showInvalidated = true + rxBus.send(EventTreatmentUpdateGui()) + true + } + + R.id.nav_hide_invalidated -> { + showInvalidated = false + rxBus.send(EventTreatmentUpdateGui()) + true + } + + else -> false + } + } + + inner class RemoveActionModeCallback : ActionMode.Callback { + + override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { + mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) + selectedItems = mutableListOf() + mode.title = rh.gs(R.string.count_selected, selectedItems.size) + binding.recyclerview.adapter?.notifyDataSetChanged() + return true + } + + override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?) = false + + override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { + return when (item.itemId) { + R.id.remove_selected -> { + removeSelected() + mode.finish() + true + } + + else -> false + } + } + + override fun onDestroyActionMode(mode: ActionMode?) { + removeActionMode = null + binding.recyclerview.adapter?.notifyDataSetChanged() + } + } + + private fun getConfirmationText(): String { + if (selectedItems.size == 1) { + val tempBasal = selectedItems.first() + val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED + val profile = profileFunction.getProfile(dateUtil.now()) + if (profile != null) + return "${if (isFakeExtended) rh.gs(R.string.extended_bolus) else rh.gs(R.string.tempbasal_label)}: ${tempBasal.toStringFull(profile, dateUtil)}\n" + + "${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(tempBasal.timestamp)}" + } + return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) + } + + private fun removeSelected() { + // TODO check if item should not be delete val profile = profileFunction.getProfile(dateUtil.now()) == null + if (selectedItems.size > 0) + activity?.let { activity -> + OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { + selectedItems.forEach { tempBasal -> + var extendedBolus: ExtendedBolus? = null + val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED + if (isFakeExtended) { + val eb = repository.getExtendedBolusActiveAt(tempBasal.timestamp).blockingGet() + extendedBolus = if (eb is ValueWrapper.Existing) eb.value else null + } + if (isFakeExtended && extendedBolus != null) { + uel.log( + Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments, + ValueWithUnit.Timestamp(extendedBolus.timestamp), + ValueWithUnit.Insulin(extendedBolus.amount), + ValueWithUnit.UnitPerHour(extendedBolus.rate), + ValueWithUnit.Minute(TimeUnit.MILLISECONDS.toMinutes(extendedBolus.duration).toInt()) + ) + disposable += repository.runTransactionForResult(InvalidateExtendedBolusTransaction(extendedBolus.id)) + .subscribe( + { aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) }) + } else if (!isFakeExtended) { + uel.log( + Action.TEMP_BASAL_REMOVED, Sources.Treatments, + ValueWithUnit.Timestamp(tempBasal.timestamp), + if (tempBasal.isAbsolute) ValueWithUnit.UnitPerHour(tempBasal.rate) else ValueWithUnit.Percent(tempBasal.rate.toInt()), + ValueWithUnit.Minute(T.msecs(tempBasal.duration).mins().toInt()) + ) + disposable += repository.runTransactionForResult(InvalidateTemporaryBasalTransaction(tempBasal.id)) + .subscribe( + { aapsLogger.debug(LTag.DATABASE, "Removed temporary basal $tempBasal") }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) }) + } + } + }) + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt index 4d3620052b..13a1b3de09 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt @@ -1,9 +1,7 @@ package info.nightscout.androidaps.activities.fragments import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup +import android.view.* import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment @@ -30,6 +28,7 @@ import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import java.util.concurrent.TimeUnit import javax.inject.Inject @@ -51,7 +50,7 @@ class TreatmentsUserEntryFragment : DaggerFragment() { private val millsToThePastFiltered = T.days(30).msecs() private val millsToThePastUnFiltered = T.days(3).msecs() - + private var showLoop = false private var _binding: TreatmentsUserEntryFragmentBinding? = null // This property is only valid between onCreateView and @@ -63,35 +62,33 @@ class TreatmentsUserEntryFragment : DaggerFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + setHasOptionsMenu(true) binding.recyclerview.setHasFixedSize(true) binding.recyclerview.layoutManager = LinearLayoutManager(view.context) - binding.ueExportToXml.setOnClickListener { - activity?.let { activity -> - OKDialog.showConfirmation(activity, rh.gs(R.string.ue_export_to_csv) + "?") { - uel.log(Action.EXPORT_CSV, Sources.Treatments) - importExportPrefs.exportUserEntriesCsv(activity) - } + } + + fun exportUserEnteries() { + activity?.let { activity -> + OKDialog.showConfirmation(activity, rh.gs(R.string.ue_export_to_csv) + "?") { + uel.log(Action.EXPORT_CSV, Sources.Treatments) + importExportPrefs.exportUserEntriesCsv(activity) } } - binding.showLoop.setOnCheckedChangeListener { _, _ -> - rxBus.send(EventTreatmentUpdateGui()) - } } fun swapAdapter() { val now = System.currentTimeMillis() - if (binding.showLoop.isChecked) - disposable.add( repository - .getUserEntryDataFromTime(now - millsToThePastUnFiltered) - .observeOn(aapsSchedulers.main) - .subscribe { list -> binding.recyclerview.swapAdapter(UserEntryAdapter(list), true) } - ) - else - disposable.add( repository - .getUserEntryFilteredDataFromTime(now - millsToThePastFiltered) - .observeOn(aapsSchedulers.main) - .subscribe { list -> binding.recyclerview.swapAdapter(UserEntryAdapter(list), true) } - ) + disposable += + if (showLoop) + repository + .getUserEntryDataFromTime(now - millsToThePastUnFiltered) + .observeOn(aapsSchedulers.main) + .subscribe { list -> binding.recyclerview.swapAdapter(UserEntryAdapter(list), true) } + else + repository + .getUserEntryFilteredDataFromTime(now - millsToThePastFiltered) + .observeOn(aapsSchedulers.main) + .subscribe { list -> binding.recyclerview.swapAdapter(UserEntryAdapter(list), true) } } @Synchronized @@ -99,15 +96,15 @@ class TreatmentsUserEntryFragment : DaggerFragment() { super.onResume() swapAdapter() - disposable.add(rxBus + disposable += rxBus .toObservable(EventPreferenceChange::class.java) .observeOn(aapsSchedulers.io) - .subscribe({ swapAdapter() }, fabricPrivacy::logException)) - disposable.add(rxBus + .subscribe({ swapAdapter() }, fabricPrivacy::logException) + disposable += rxBus .toObservable(EventTreatmentUpdateGui::class.java) .observeOn(aapsSchedulers.io) .debounce(1L, TimeUnit.SECONDS) - .subscribe({ swapAdapter() }, fabricPrivacy::logException)) + .subscribe({ swapAdapter() }, fabricPrivacy::logException) } @Synchronized @@ -132,7 +129,7 @@ class TreatmentsUserEntryFragment : DaggerFragment() { override fun onBindViewHolder(holder: UserEntryViewHolder, position: Int) { val current = entries[position] - val sameDayPrevious = position > 0 && dateUtil.isSameDay(current.timestamp, entries[position-1].timestamp) + val sameDayPrevious = position > 0 && dateUtil.isSameDay(current.timestamp, entries[position - 1].timestamp) holder.binding.date.visibility = sameDayPrevious.not().toVisibility() holder.binding.date.text = dateUtil.dateString(current.timestamp) holder.binding.time.text = dateUtil.timeStringWithSeconds(current.timestamp) @@ -152,7 +149,41 @@ class TreatmentsUserEntryFragment : DaggerFragment() { val binding = TreatmentsUserEntryItemBinding.bind(itemView) } - override fun getItemCount(): Int = entries.size + override fun getItemCount() = entries.size } -} \ No newline at end of file + override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { + inflater.inflate(R.menu.menu_treatments_user_entry, menu) + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onPrepareOptionsMenu(menu: Menu) { + menu.findItem(R.id.nav_hide_loop)?.isVisible = showLoop + menu.findItem(R.id.nav_show_loop)?.isVisible = !showLoop + + return super.onPrepareOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.nav_show_loop -> { + showLoop = true + rxBus.send(EventTreatmentUpdateGui()) + true + } + + R.id.nav_hide_loop -> { + showLoop = false + rxBus.send(EventTreatmentUpdateGui()) + true + } + + R.id.nav_export -> { + exportUserEnteries() + true + } + + else -> false + } + } +} diff --git a/app/src/main/res/layout/treatments_bolus_carbs_fragment.xml b/app/src/main/res/layout/treatments_bolus_carbs_fragment.xml index 1012d218e3..388a6a9976 100644 --- a/app/src/main/res/layout/treatments_bolus_carbs_fragment.xml +++ b/app/src/main/res/layout/treatments_bolus_carbs_fragment.xml @@ -1,54 +1,10 @@ - - - - - - - - - - - - - + android:contentDescription="@string/select_for_removal" + android:visibility="gone" /> + + - - - - - - - - - - - - - + android:contentDescription="@string/select_for_removal" + android:visibility="gone" /> diff --git a/app/src/main/res/layout/treatments_extendedbolus_fragment.xml b/app/src/main/res/layout/treatments_extendedbolus_fragment.xml index 8434b39e86..945a861bb1 100644 --- a/app/src/main/res/layout/treatments_extendedbolus_fragment.xml +++ b/app/src/main/res/layout/treatments_extendedbolus_fragment.xml @@ -1,34 +1,10 @@ - - - - - - - - - + android:contentDescription="@string/select_for_removal" + android:visibility="gone" /> + - - - - - - - - - - - + android:contentDescription="@string/select_for_removal" + android:visibility="gone" /> diff --git a/app/src/main/res/layout/treatments_tempbasals_fragment.xml b/app/src/main/res/layout/treatments_tempbasals_fragment.xml index b7dba96815..9ef25cff3e 100644 --- a/app/src/main/res/layout/treatments_tempbasals_fragment.xml +++ b/app/src/main/res/layout/treatments_tempbasals_fragment.xml @@ -1,36 +1,10 @@ - - - - - - - - - - - + android:contentDescription="@string/select_for_removal" + android:visibility="gone" /> - - - - - - - - - - - + android:contentDescription="@string/select_for_removal" + android:visibility="gone" /> diff --git a/app/src/main/res/layout/treatments_user_entry_fragment.xml b/app/src/main/res/layout/treatments_user_entry_fragment.xml index 2244b94f6d..8479bbfde9 100644 --- a/app/src/main/res/layout/treatments_user_entry_fragment.xml +++ b/app/src/main/res/layout/treatments_user_entry_fragment.xml @@ -6,40 +6,6 @@ android:orientation="vertical" tools:context="info.nightscout.androidaps.activities.fragments.TreatmentsUserEntryFragment"> - - - - - - - - - - - + + + + diff --git a/app/src/main/res/menu/menu_treatments_carbs_bolus.xml b/app/src/main/res/menu/menu_treatments_carbs_bolus.xml new file mode 100644 index 0000000000..c45d9562d3 --- /dev/null +++ b/app/src/main/res/menu/menu_treatments_carbs_bolus.xml @@ -0,0 +1,25 @@ + + + + + + + + + diff --git a/app/src/main/res/menu/menu_treatments_careportal.xml b/app/src/main/res/menu/menu_treatments_careportal.xml new file mode 100644 index 0000000000..7a90a0f10a --- /dev/null +++ b/app/src/main/res/menu/menu_treatments_careportal.xml @@ -0,0 +1,25 @@ + + + + + + + + + diff --git a/app/src/main/res/menu/menu_treatments_extended_bolus.xml b/app/src/main/res/menu/menu_treatments_extended_bolus.xml new file mode 100644 index 0000000000..2822a53819 --- /dev/null +++ b/app/src/main/res/menu/menu_treatments_extended_bolus.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/app/src/main/res/menu/menu_treatments_profile_switch.xml b/app/src/main/res/menu/menu_treatments_profile_switch.xml new file mode 100644 index 0000000000..2822a53819 --- /dev/null +++ b/app/src/main/res/menu/menu_treatments_profile_switch.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/app/src/main/res/menu/menu_treatments_temp_basal.xml b/app/src/main/res/menu/menu_treatments_temp_basal.xml new file mode 100644 index 0000000000..2822a53819 --- /dev/null +++ b/app/src/main/res/menu/menu_treatments_temp_basal.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/app/src/main/res/menu/menu_treatments_temp_target.xml b/app/src/main/res/menu/menu_treatments_temp_target.xml new file mode 100644 index 0000000000..751c678f12 --- /dev/null +++ b/app/src/main/res/menu/menu_treatments_temp_target.xml @@ -0,0 +1,21 @@ + + + + + + + + diff --git a/app/src/main/res/menu/menu_treatments_user_entry.xml b/app/src/main/res/menu/menu_treatments_user_entry.xml new file mode 100644 index 0000000000..cab552390e --- /dev/null +++ b/app/src/main/res/menu/menu_treatments_user_entry.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fa3550bae6..018baa8b9c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -826,6 +826,9 @@ When sensitivity is detected, raise the target glucose keep_screen_on Clean AndroidAPS started + Show invalidated + Hide invalidated + Remove items Stored settings found Attention: If you activate and connect to a hardware pump, AndroidAPS will copy the basal settings from the profile to the pump, overwriting the existing basal rate stored on the pump. Make sure you have the correct basal setting in AndroidAPS. If you are not sure or don\'t want to overwrite the basal settings on your pump, press cancel and repeat switching to the pump at a later time. Treatment data incomplete @@ -1207,4 +1210,14 @@ Unknown action command: Percentage Application default + Refresh from Nightscout + Remove selected items + Select for removal + Profile changes + Temp Targets + Carbs and bolus + Are you sure you want to remove %1$d items + Hide loop + Show loop + %1$d selected diff --git a/core/src/main/res/drawable/ic_close.xml b/core/src/main/res/drawable/ic_close.xml new file mode 100644 index 0000000000..70db409b33 --- /dev/null +++ b/core/src/main/res/drawable/ic_close.xml @@ -0,0 +1,5 @@ + + + diff --git a/core/src/main/res/values/layout.xml b/core/src/main/res/values/layout.xml index 5629fe5956..045d08e4e1 100644 --- a/core/src/main/res/values/layout.xml +++ b/core/src/main/res/values/layout.xml @@ -3,6 +3,8 @@ @color/colorPrimary @color/colorPrimaryDark @color/colorAccent + true + @drawable/ic_close \ No newline at end of file diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 76428aa88f..4d6b4b1157 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -469,6 +469,7 @@ STAT RESET DELETE LOGS DELETE FUTURE TREATMENTS + Delete future treatments EXPORT SETTINGS IMPORT SETTINGS RESET DATABASES From 967d8bb9d30ee9fad1a835aad7f203916f4f21f0 Mon Sep 17 00:00:00 2001 From: Andries Smit Date: Wed, 23 Feb 2022 08:51:10 +0100 Subject: [PATCH 23/40] chore: treatments menu code cleanup --- .../fragments/TreatmentsBolusCarbsFragment.kt | 76 +++++++++---------- .../fragments/TreatmentsCareportalFragment.kt | 8 +- .../TreatmentsExtendedBolusesFragment.kt | 3 +- .../TreatmentsProfileSwitchFragment.kt | 8 +- .../fragments/TreatmentsTempTargetFragment.kt | 8 +- .../TreatmentsTemporaryBasalsFragment.kt | 7 +- .../fragments/TreatmentsUserEntryFragment.kt | 8 +- core/src/main/res/drawable/ic_close.xml | 13 +++- 8 files changed, 61 insertions(+), 70 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt index dd359ef07d..5840cc1a35 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt @@ -86,7 +86,6 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { private var showInvalidated = false private var removeActionMode: ActionMode? = null - // val TAG = "TreatmentMenu" private var toolbar: Toolbar? = null override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = @@ -128,34 +127,35 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { fun swapAdapter() { val now = System.currentTimeMillis() - disposable += if (showInvalidated) - carbsMealLinksWithInvalid(now) - .zipWith(bolusMealLinksWithInvalid(now)) { first, second -> first + second } - .zipWith(calcResultMealLinksWithInvalid(now)) { first, second -> first + second } - .map { ml -> - ml.sortedByDescending { - it.carbs?.timestamp ?: it.bolus?.timestamp - ?: it.bolusCalculatorResult?.timestamp + disposable += + if (showInvalidated) + carbsMealLinksWithInvalid(now) + .zipWith(bolusMealLinksWithInvalid(now)) { first, second -> first + second } + .zipWith(calcResultMealLinksWithInvalid(now)) { first, second -> first + second } + .map { ml -> + ml.sortedByDescending { + it.carbs?.timestamp ?: it.bolus?.timestamp + ?: it.bolusCalculatorResult?.timestamp + } } - } - .observeOn(aapsSchedulers.main) - .subscribe { list -> - binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) - } - else - carbsMealLinks(now) - .zipWith(bolusMealLinks(now)) { first, second -> first + second } - .zipWith(calcResultMealLinks(now)) { first, second -> first + second } - .map { ml -> - ml.sortedByDescending { - it.carbs?.timestamp ?: it.bolus?.timestamp - ?: it.bolusCalculatorResult?.timestamp + .observeOn(aapsSchedulers.main) + .subscribe { list -> + binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) + } + else + carbsMealLinks(now) + .zipWith(bolusMealLinks(now)) { first, second -> first + second } + .zipWith(calcResultMealLinks(now)) { first, second -> first + second } + .map { ml -> + ml.sortedByDescending { + it.carbs?.timestamp ?: it.bolus?.timestamp + ?: it.bolusCalculatorResult?.timestamp + } + } + .observeOn(aapsSchedulers.main) + .subscribe { list -> + binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) } - } - .observeOn(aapsSchedulers.main) - .subscribe { list -> - binding.recyclerview.swapAdapter(RecyclerViewAdapter(list), true) - } } @@ -262,10 +262,10 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { } removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size) } - holder.binding.cbBolusRemove.visibility = ((ml.bolus?.isValid == true) && (removeActionMode != null)).toVisibility() + holder.binding.cbBolusRemove.visibility = ((ml.bolus?.isValid == true) && removeActionMode != null).toVisibility() holder.binding.cbBolusRemove.setOnCheckedChangeListener(onChange) - holder.binding.cbCarbsRemove.visibility = (ml.carbs?.isValid == true && (removeActionMode != null)).toVisibility() + holder.binding.cbCarbsRemove.visibility = (ml.carbs?.isValid == true && removeActionMode != null).toVisibility() holder.binding.cbCarbsRemove.setOnCheckedChangeListener(onChange) holder.binding.calculation.tag = ml @@ -310,8 +310,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { return super.onPrepareOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { + override fun onOptionsItemSelected(item: MenuItem): Boolean = + when (item.itemId) { R.id.nav_remove_items -> { removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback()) true @@ -335,15 +335,14 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { } R.id.nav_refresh_ns -> { - refreshFromNightScout() + refreshFromNightscout() true } else -> false } - } - private fun refreshFromNightScout() { + private fun refreshFromNightscout() { activity?.let { activity -> OKDialog.showConfirmation(activity, rh.gs(R.string.refresheventsfromnightscout) + "?") { uel.log(Action.TREATMENTS_NS_REFRESH, Sources.Treatments) @@ -457,13 +456,11 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { val mealLink = selectedItems.first() val bolus = mealLink.bolus if (bolus != null) - return rh.gs(R.string.configbuilder_insulin) + ": " + - rh.gs(R.string.formatinsulinunits, bolus.amount) + "\n" + + return rh.gs(R.string.configbuilder_insulin) + ": " + rh.gs(R.string.formatinsulinunits, bolus.amount) + "\n" + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(bolus.timestamp) val carbs = mealLink.carbs if (carbs != null) - return rh.gs(R.string.carbs) + ": " + - rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carbs.amount.toInt()) + "\n" + + return rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carbs.amount.toInt()) + "\n" + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(carbs.timestamp) } return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) @@ -499,9 +496,6 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { ) } } - selectedItems = mutableListOf() - }, Runnable { - selectedItems = mutableListOf() }) } } diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt index 59efc40861..b2230d9caa 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt @@ -171,7 +171,7 @@ class TreatmentsCareportalFragment : DaggerFragment() { holder.binding.duration.text = if (therapyEvent.duration == 0L) "" else dateUtil.niceTimeScalar(therapyEvent.duration, rh) holder.binding.note.text = therapyEvent.note holder.binding.type.text = translator.translate(therapyEvent.type) - holder.binding.cbRemove.visibility = (therapyEvent.isValid && (removeActionMode != null)).toVisibility() + holder.binding.cbRemove.visibility = (therapyEvent.isValid && removeActionMode != null).toVisibility() holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> if (value) { selectedItems.add(therapyEvent) @@ -193,7 +193,6 @@ class TreatmentsCareportalFragment : DaggerFragment() { } - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.menu_treatments_careportal, menu) super.onCreateOptionsMenu(menu, inflater) @@ -208,8 +207,8 @@ class TreatmentsCareportalFragment : DaggerFragment() { return super.onPrepareOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { + override fun onOptionsItemSelected(item: MenuItem): Boolean = + when (item.itemId) { R.id.nav_remove_items -> { removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback()) true @@ -239,7 +238,6 @@ class TreatmentsCareportalFragment : DaggerFragment() { else -> false } - } inner class RemoveActionModeCallback : ActionMode.Callback { diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt index af1499bf76..c4ac1aff5b 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt @@ -67,7 +67,6 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { private var showInvalidated = false private var removeActionMode: ActionMode? = null private var toolbar: Toolbar? = null - // val TAG = "TreatmentMenu" override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = TreatmentsExtendedbolusFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root @@ -149,7 +148,7 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { holder.binding.iob.text = rh.gs(R.string.formatinsulinunits, iob.iob) holder.binding.ratio.text = rh.gs(R.string.pump_basebasalrate, extendedBolus.rate) if (iob.iob != 0.0) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.insulin.currentTextColor) - holder.binding.cbRemove.visibility = (extendedBolus.isValid && (removeActionMode != null)).toVisibility() + holder.binding.cbRemove.visibility = (extendedBolus.isValid && removeActionMode != null).toVisibility() holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> if (value) { selectedItems.add(extendedBolus) diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt index 3d2af3afd0..38073e13ad 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt @@ -188,7 +188,8 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { holder.binding.date.text = dateUtil.dateString(profileSwitch.timestamp) holder.binding.time.text = dateUtil.timeString(profileSwitch.timestamp) holder.binding.duration.text = rh.gs(R.string.format_mins, T.msecs(profileSwitch.duration ?: 0L).mins()) - holder.binding.name.text = if (profileSwitch is ProfileSealed.PS) profileSwitch.value.getCustomizedName() else if (profileSwitch is ProfileSealed.EPS) profileSwitch.value.originalCustomizedName else "" + holder.binding.name.text = if (profileSwitch is ProfileSealed.PS) profileSwitch.value.getCustomizedName() + else if (profileSwitch is ProfileSealed.EPS) profileSwitch.value.originalCustomizedName else "" if (profileSwitch.isInProgress(dateUtil)) holder.binding.date.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.date.setTextColor(holder.binding.duration.currentTextColor) holder.binding.clone.tag = profileSwitch @@ -282,8 +283,8 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { return super.onPrepareOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { + override fun onOptionsItemSelected(item: MenuItem): Boolean = + when (item.itemId) { R.id.nav_remove_items -> { removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback()) true @@ -308,7 +309,6 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { else -> false } - } inner class RemoveActionModeCallback : ActionMode.Callback { diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt index 479f0008de..846c1122e0 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt @@ -173,7 +173,7 @@ class TreatmentsTempTargetFragment : DaggerFragment() { val tempTarget = tempTargetList[position] holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility() - holder.binding.cbRemove.visibility = (tempTarget.isValid && (removeActionMode != null)).toVisibility() + holder.binding.cbRemove.visibility = (tempTarget.isValid && removeActionMode != null).toVisibility() holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> if (value) { selectedItems.add(tempTarget) @@ -211,7 +211,6 @@ class TreatmentsTempTargetFragment : DaggerFragment() { } private fun removeSelected() { - // TODO check if item should not be delete val profile = profileFunction.getProfile(dateUtil.now()) == null if (selectedItems.size > 0) activity?.let { activity -> OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { @@ -247,8 +246,8 @@ class TreatmentsTempTargetFragment : DaggerFragment() { return super.onPrepareOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { + override fun onOptionsItemSelected(item: MenuItem): Boolean = + when (item.itemId) { R.id.nav_remove_items -> { removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback()) true @@ -273,7 +272,6 @@ class TreatmentsTempTargetFragment : DaggerFragment() { else -> false } - } inner class RemoveActionModeCallback : ActionMode.Callback { diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt index 4e166fc46f..b24f062004 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt @@ -191,7 +191,7 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { holder.binding.emulatedSuspendFlag.visibility = (tempBasal.type == TemporaryBasal.Type.EMULATED_PUMP_SUSPEND).toVisibility() holder.binding.superBolusFlag.visibility = (tempBasal.type == TemporaryBasal.Type.SUPERBOLUS).toVisibility() if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor) - holder.binding.cbRemove.visibility = (tempBasal.isValid && (removeActionMode != null)).toVisibility() + holder.binding.cbRemove.visibility = (tempBasal.isValid && removeActionMode != null).toVisibility() holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> if (value) { selectedItems.add(tempBasal) @@ -226,8 +226,8 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { return super.onPrepareOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { + override fun onOptionsItemSelected(item: MenuItem): Boolean = + when (item.itemId) { R.id.nav_remove_items -> { removeActionMode = toolbar?.startActionMode(RemoveActionModeCallback()) true @@ -247,7 +247,6 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { else -> false } - } inner class RemoveActionModeCallback : ActionMode.Callback { diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt index 13a1b3de09..071054d79c 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsUserEntryFragment.kt @@ -53,8 +53,7 @@ class TreatmentsUserEntryFragment : DaggerFragment() { private var showLoop = false private var _binding: TreatmentsUserEntryFragmentBinding? = null - // This property is only valid between onCreateView and - // onDestroyView. + // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = @@ -164,8 +163,8 @@ class TreatmentsUserEntryFragment : DaggerFragment() { return super.onPrepareOptionsMenu(menu) } - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { + override fun onOptionsItemSelected(item: MenuItem): Boolean = + when (item.itemId) { R.id.nav_show_loop -> { showLoop = true rxBus.send(EventTreatmentUpdateGui()) @@ -185,5 +184,4 @@ class TreatmentsUserEntryFragment : DaggerFragment() { else -> false } - } } diff --git a/core/src/main/res/drawable/ic_close.xml b/core/src/main/res/drawable/ic_close.xml index 70db409b33..49ac6f1398 100644 --- a/core/src/main/res/drawable/ic_close.xml +++ b/core/src/main/res/drawable/ic_close.xml @@ -1,5 +1,10 @@ - - + + From 033270f6a70792b473d05075f89efc567e7081a3 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 23 Feb 2022 09:47:38 +0100 Subject: [PATCH 24/40] New Crowdin updates (#1321) * Update source file strings.xml * New translations strings.xml (Romanian) * New translations strings.xml (Irish) * New translations strings.xml (Hebrew) * New translations strings.xml (Hebrew) * New translations strings.xml (Hebrew) * New translations strings.xml (Hungarian) * New translations strings.xml (German) * New translations strings.xml (Italian) * New translations strings.xml (Italian) * New translations strings.xml (Korean) * New translations strings.xml (Korean) * New translations strings.xml (Lithuanian) * New translations strings.xml (Lithuanian) * New translations strings.xml (Dutch) * New translations strings.xml (Greek) * New translations strings.xml (German) * New translations strings.xml (Romanian) * New translations strings.xml (Bulgarian) * New translations strings.xml (French) * New translations strings.xml (French) * New translations strings.xml (Spanish) * New translations strings.xml (Spanish) * New translations strings.xml (Spanish) * New translations strings.xml (Afrikaans) * New translations strings.xml (Bulgarian) * New translations strings.xml (German) * New translations strings.xml (Catalan) * New translations strings.xml (Czech) * New translations strings.xml (Czech) * New translations strings.xml (Czech) * New translations strings.xml (Danish) * New translations strings.xml (Danish) * New translations strings.xml (Danish) * New translations strings.xml (Dutch) * New translations strings.xml (Dutch) * New translations strings.xml (Portuguese, Brazilian) * New translations strings.xml (Portuguese, Brazilian) * New translations strings.xml (Norwegian) * New translations strings.xml (Russian) * New translations strings.xml (Norwegian) * New translations strings.xml (Norwegian) * New translations strings.xml (Polish) * New translations strings.xml (Polish) * New translations strings.xml (Portuguese) * New translations strings.xml (Portuguese) * New translations strings.xml (Russian) * New translations strings.xml (Russian) * New translations strings.xml (Slovak) * New translations strings.xml (Slovak) * New translations strings.xml (Slovak) * New translations strings.xml (Swedish) * New translations strings.xml (Swedish) * New translations strings.xml (Turkish) * New translations strings.xml (Turkish) * New translations strings.xml (Turkish) * New translations strings.xml (Chinese Simplified) * New translations exam.xml (Turkish) * New translations exam.xml (Portuguese, Brazilian) * New translations strings.xml (Spanish) * New translations strings.xml (Czech) * New translations strings.xml (German) * New translations strings.xml (Hebrew) * New translations strings.xml (Norwegian) * New translations strings.xml (Russian) * New translations strings.xml (Slovak) * New translations strings.xml (Turkish) * New translations strings.xml (Danish) * New translations strings.xml (Dutch) * New translations strings.xml (French) * New translations strings.xml (French) * New translations strings.xml (French) * New translations strings.xml (French) * New translations strings.xml (French) * New translations strings.xml (German) * New translations strings.xml (Norwegian) * New translations strings.xml (Norwegian) * New translations strings.xml (Slovak) * New translations strings.xml (Hebrew) * Update source file strings.xml * Update source file strings.xml * New translations strings.xml (French) * New translations strings.xml (Czech) * New translations strings.xml (Norwegian) * New translations strings.xml (Turkish) * New translations strings.xml (Dutch) * New translations strings.xml (Czech) * New translations strings.xml (Dutch) * New translations strings.xml (Dutch) * New translations strings.xml (Dutch) * New translations strings.xml (Dutch) * New translations strings.xml (Hebrew) * New translations strings.xml (Slovak) * New translations strings.xml (Slovak) * New translations strings.xml (Slovak) * New translations strings.xml (Norwegian) * New translations strings.xml (Turkish) * New translations strings.xml (Polish) * New translations strings.xml (Turkish) * Update source file strings.xml * Update source file strings.xml * New translations strings.xml (Russian) * New translations strings.xml (Hebrew) * New translations strings.xml (Norwegian) * New translations strings.xml (Norwegian) * New translations strings.xml (Turkish) * New translations strings.xml (Turkish) * New translations strings.xml (Turkish) * New translations strings.xml (Swedish) * New translations strings.xml (Swedish) * New translations strings.xml (Swedish) * New translations strings.xml (Swedish) * New translations strings.xml (Swedish) * New translations strings.xml (Turkish) * New translations strings.xml (Czech) * New translations strings.xml (Czech) * New translations strings.xml (Spanish) * New translations strings.xml (Spanish) * New translations strings.xml (Spanish) * New translations strings.xml (Spanish) * New translations exam.xml (Portuguese, Brazilian) * New translations exam.xml (Portuguese, Brazilian) * New translations objectives.xml (Portuguese, Brazilian) --- app/src/main/res/values-af-rZA/strings.xml | 2 +- app/src/main/res/values-bg-rBG/strings.xml | 4 +- app/src/main/res/values-ca-rES/strings.xml | 1 + app/src/main/res/values-cs-rCZ/strings.xml | 77 +++++++++++++++++- app/src/main/res/values-da-rDK/strings.xml | 7 +- app/src/main/res/values-de-rDE/strings.xml | 38 ++++++++- app/src/main/res/values-el-rGR/strings.xml | 2 +- app/src/main/res/values-es-rES/strings.xml | 77 +++++++++++++++++- app/src/main/res/values-fr-rFR/strings.xml | 72 ++++++++++++++++- app/src/main/res/values-ga-rIE/strings.xml | 3 +- app/src/main/res/values-hu-rHU/strings.xml | 1 + app/src/main/res/values-it-rIT/strings.xml | 4 +- app/src/main/res/values-iw-rIL/strings.xml | 39 +++++++-- app/src/main/res/values-ko-rKR/strings.xml | 4 +- app/src/main/res/values-lt-rLT/strings.xml | 4 +- app/src/main/res/values-nl-rNL/strings.xml | 74 ++++++++++++++++- app/src/main/res/values-no-rNO/strings.xml | 75 ++++++++++++++++- app/src/main/res/values-pl-rPL/strings.xml | 4 +- app/src/main/res/values-pt-rBR/exam.xml | 9 +-- app/src/main/res/values-pt-rBR/objectives.xml | 2 + app/src/main/res/values-pt-rBR/strings.xml | 3 +- app/src/main/res/values-pt-rPT/strings.xml | 4 +- app/src/main/res/values-ro-rRO/strings.xml | 4 +- app/src/main/res/values-ru-rRU/strings.xml | 30 ++++++- app/src/main/res/values-sk-rSK/strings.xml | 80 +++++++++++++++++-- app/src/main/res/values-sv-rSE/strings.xml | 75 ++++++++++++++++- app/src/main/res/values-tr-rTR/exam.xml | 2 +- app/src/main/res/values-tr-rTR/strings.xml | 77 +++++++++++++++++- app/src/main/res/values-zh-rCN/strings.xml | 2 +- .../src/main/res/values-cs-rCZ/strings.xml | 1 + .../src/main/res/values-de-rDE/strings.xml | 1 + .../src/main/res/values-es-rES/strings.xml | 1 + .../src/main/res/values-fr-rFR/strings.xml | 1 + .../src/main/res/values-iw-rIL/strings.xml | 1 + .../src/main/res/values-nl-rNL/strings.xml | 1 + .../src/main/res/values-no-rNO/strings.xml | 1 + .../src/main/res/values-ru-rRU/strings.xml | 1 + .../src/main/res/values-sk-rSK/strings.xml | 1 + .../src/main/res/values-sv-rSE/strings.xml | 1 + .../src/main/res/values-tr-rTR/strings.xml | 1 + combo/src/main/res/values-cs-rCZ/strings.xml | 6 ++ combo/src/main/res/values-es-rES/strings.xml | 6 ++ combo/src/main/res/values-no-rNO/strings.xml | 6 ++ combo/src/main/res/values-ru-rRU/strings.xml | 6 ++ combo/src/main/res/values-sv-rSE/strings.xml | 6 ++ combo/src/main/res/values-tr-rTR/strings.xml | 6 ++ core/src/main/res/values-cs-rCZ/strings.xml | 9 +++ core/src/main/res/values-da-rDK/strings.xml | 5 ++ core/src/main/res/values-de-rDE/strings.xml | 9 +++ core/src/main/res/values-es-rES/strings.xml | 9 +++ core/src/main/res/values-fr-rFR/strings.xml | 9 +++ core/src/main/res/values-iw-rIL/strings.xml | 7 ++ core/src/main/res/values-nl-rNL/strings.xml | 9 +++ core/src/main/res/values-no-rNO/strings.xml | 9 +++ core/src/main/res/values-ru-rRU/strings.xml | 9 +++ core/src/main/res/values-sk-rSK/strings.xml | 9 +++ core/src/main/res/values-sv-rSE/strings.xml | 9 +++ core/src/main/res/values-tr-rTR/strings.xml | 9 +++ .../src/main/res/values-tr-rTR/strings.xml | 1 - .../src/main/res/values-da-rDK/strings.xml | 2 +- .../src/main/res/values-nl-rNL/strings.xml | 2 + .../src/main/res/values-iw-rIL/strings.xml | 2 +- wear/src/main/res/values-bg-rBG/strings.xml | 14 ---- wear/src/main/res/values-cs-rCZ/strings.xml | 50 +++++++++--- wear/src/main/res/values-da-rDK/strings.xml | 14 ---- wear/src/main/res/values-de-rDE/strings.xml | 14 ---- wear/src/main/res/values-es-rES/strings.xml | 34 ++++++-- wear/src/main/res/values-fr-rFR/strings.xml | 50 +++++++++--- wear/src/main/res/values-it-rIT/strings.xml | 14 ---- wear/src/main/res/values-iw-rIL/strings.xml | 15 +--- wear/src/main/res/values-ko-rKR/strings.xml | 14 ---- wear/src/main/res/values-lt-rLT/strings.xml | 14 ---- wear/src/main/res/values-nl-rNL/strings.xml | 52 ++++++++---- wear/src/main/res/values-no-rNO/strings.xml | 52 ++++++++---- wear/src/main/res/values-pl-rPL/strings.xml | 29 ++++--- wear/src/main/res/values-pt-rBR/strings.xml | 14 ---- wear/src/main/res/values-pt-rPT/strings.xml | 14 ---- wear/src/main/res/values-ro-rRO/strings.xml | 14 ---- wear/src/main/res/values-ru-rRU/strings.xml | 14 ---- wear/src/main/res/values-sk-rSK/strings.xml | 50 +++++++++--- wear/src/main/res/values-sv-rSE/strings.xml | 50 +++++++++--- wear/src/main/res/values-tr-rTR/strings.xml | 52 ++++++++---- 82 files changed, 1158 insertions(+), 348 deletions(-) diff --git a/app/src/main/res/values-af-rZA/strings.xml b/app/src/main/res/values-af-rZA/strings.xml index 2ae889ed57..3b061e3422 100644 --- a/app/src/main/res/values-af-rZA/strings.xml +++ b/app/src/main/res/values-af-rZA/strings.xml @@ -181,7 +181,6 @@ Wear Stuur alle Data weer Oop instellings op Wear - Basale waarde: Basale waarde onder minimum. Profiel nie gestel nie! BG: Laaste BG: @@ -573,4 +572,5 @@ Projeksies Prima + diff --git a/app/src/main/res/values-bg-rBG/strings.xml b/app/src/main/res/values-bg-rBG/strings.xml index a89f952333..822b19d7ad 100644 --- a/app/src/main/res/values-bg-rBG/strings.xml +++ b/app/src/main/res/values-bg-rBG/strings.xml @@ -245,7 +245,6 @@ Часовник Изпрати отново всички дани Отвори настройките на часовника - Базал: Базалните стойности са под минимума. Не е зададен профил! КЗ: Последна КЗ: @@ -747,8 +746,6 @@ Името на профила съдържа точка.\nТова не се поддържа от НС.\nПрофилът не е качен в НС. Ниската граница на диапазона (графика) Високата граница на диапазона (графика) - Възраст: - Тегло: Номер: Изпрати Най-често използван профил: @@ -890,4 +887,5 @@ Рекалкулирани използвани данни КЗ близо до:\n%1$s\n%2$s Недостъпно + diff --git a/app/src/main/res/values-ca-rES/strings.xml b/app/src/main/res/values-ca-rES/strings.xml index 06ea06e81c..e8e60f272d 100644 --- a/app/src/main/res/values-ca-rES/strings.xml +++ b/app/src/main/res/values-ca-rES/strings.xml @@ -316,4 +316,5 @@ Canviar de perfil Sensor + diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index b73f70c2c3..1d36292713 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -25,6 +25,7 @@ Synchronizace dat s NS Stav algoritmu v roce 2017 Nejnovější algoritmus pro pokročilé uživatele + Nejnovější algoritmus pro pokročilé uživatele s dynamickým/automatickým ISF Zobrazení stavu a informací. Přístup k nejběžnějším ovládacím prvkům Zobrazení průběžného oznámení v Androidu s krátkým přehledem, co smyčka právě dělá Definujte profil, který je dostupný offline. @@ -154,7 +155,7 @@ Před importem zkontrolujte předvolby: Předvolby nelze importovat! Předvolby by neměly být importovány! - Vysvětlení problémy při importu… + Vysvětlení problémů při importu… Detaily problémů importu Import Přesto importovat (NEBEZPEČNÉ!) @@ -246,7 +247,7 @@ Wear Znovu poslat všechna data Otevřít nastavení na hodinkách Wear - Bazál: + Bazál Hodnota bazálu pod povoleným minimem. Nenastaveno! Glykémie: Poslední glykémie: @@ -267,6 +268,7 @@ KONF SMYČ OAPS + DYNSENZ MPRF PŘEH VPUM @@ -434,6 +436,7 @@ Povolit vysílání do jiných aplikací (například xDrip+). Nepovolujte, pokud máte instalovánu více než jednu instanci AAPS nebo NSClient! Povolení odesílaní OpenAPS SMB + OpenAPS SMB s dynamickým ISF Povolit UAM Povolit SMB Použít super mikro bolusy místo dočasných bazálů pro zrychlení účinku @@ -502,6 +505,7 @@ Pouze záporné Kalkulace COB Kalkulace s dočasným cílem + Procentní výpočet Smyčka povolena APS vybráno NSClient má povolení k zápisu @@ -757,8 +761,8 @@ Název profilu obsahuje tečky.\nToto není v NS podporováno.\nProfil není přenesen do NS. Spodní hodnota oblasti v rozsahu (pouze zobrazování) Horní hodnota oblasti v rozsahu (pouze zobrazování) - Věk: - Hmotnost: + Věk + Váha ID: Odeslat Nejběžnější profil: @@ -900,9 +904,74 @@ Chyby Zpomalit odesílání Stav glykémie + stáří kanyly + stáří náplasťové pumpy + Náplasťová pumpa Použita přepočítaná data Glykémie je příliš blízko:\n%1$s\n%2$s Identifikace (e-mail, jméno na FB nebo Discord atd.) Identifikace není nastavena ve vývojářském režimu + dialog + aktuální hodnota glykémie + správný výsledek v % + správný výsledek s jednotkami Nedostupný + vysoká + v rozsahu + nízká + rychle klesající + klesající + pomalu klesající + stabilní + pomalu stoupající + stoupající + rychle stoupající + žádný + neznámý + graf + kvalita glykémií + přepočítáno + dvojité položky + inzulín + glykémie + zastaralé + nastavit připomenutí + přidat nový profil + klonovat aktuální profil + odstranit aktuální profil + přidat nový do seznamu + + Dočasný cíl neznámá předvolba: %1$s + Zrušení běžícího dočasného cíle? + Různé jednotky používané na hodinkách a telefonu! + Nulový dočasný cíl - zrušení běžícího dočasného cíle? + Minimální glykémie mimo dosah! + Maximální glykémie mimo dosah! + Doč. cíl:\nMin: %1$s\nMax: %2$s\nTrvání: %3$s + Doč. cíl:\nCíl: %1$s\nTrvání: %2$s + Doč. cíl:\nDůvod: %1$s\nCíl: %2$s\nTrvání: %3$s + Rychlý bolus: %1$s\nInzulín: %2$.2fU\nSacharidy: %3$dg + Kalkulátor: \nInzulín: %1$.2fU\nSacharidy: %2$dg + Zobrazit záznam na zařízení: + Vybraný rychlý bolus již není k dispozici, obnovte prosím dlaždici + Žádná aktuální glykémie k výpočtu! + Není nastaven žádný aktivní profil! + Neznámý COB! Chybějící glykémie nebo nedávný restart aplikace? + Sacharidy mimo povolený rozsah! + Kalk (IC: %2$.1f, ISF: %2$.1f) z:\" + Sacharidy: %1$.2fU + COB: %1$.0fg %2$.2fU + Glykémie: %1$.2fU + Bazální IOB: %1$.2fU + Bolusové IOB: %1$.2fU + Superbolus: %1$.2fU + 15\' trend: %1$.2fU + Procentuální hodnota: %1$.2fU x %2$d%% ≈ %3$.2fU + Inzulím mimo povolený rozsah!\nNelze podat %1$.2fU + Doč. cíl: %1$s + %1$s – %2$s + Pumpa není k dispozici! + Neznámý příkaz k akci: + Procentní podíl + Výchozí nastavení aplikace diff --git a/app/src/main/res/values-da-rDK/strings.xml b/app/src/main/res/values-da-rDK/strings.xml index cf74f37558..2ba454c6ed 100644 --- a/app/src/main/res/values-da-rDK/strings.xml +++ b/app/src/main/res/values-da-rDK/strings.xml @@ -246,7 +246,6 @@ Ur Send alle data igen Åbn indstillinger på ur - Basal rate: Basal værdi under minimum. Profil ikke angivet! BG: Sidste BG: @@ -757,8 +756,6 @@ Profilnavn indeholder punktum.\nDette understøttes ikke af NS.\nProfilen er ikke uploadet til NS. Nedre værdi for målområde (kun visning) Øvre værdi for målområde (kun visning) - Alder: - Vægt: ID: Send Mest almindelige profil: @@ -900,9 +897,13 @@ Fejl Reducer upload hastighed BG data status + Indstik alder + patch pumpe alder + Patch pumpe Genberegnede data anvendt BG for tæt:\n%1$s\n%2$s Identifikation (e-mail, FB eller Discord alias osv.) Identifikation ikke indstillet i udvikler-tilstand Ikke tilgængelig + diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index 4d8b0f600d..b393ee8e2a 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -246,7 +246,7 @@ Wear Alle Daten erneut senden Öffne Einstellungen auf der Uhr - Basalrate: + Basalrate Wert der Basalrate unter Minimum. Profil nicht gesetzt! BZ: Letzter BZ: @@ -758,8 +758,8 @@ Unerwartetes Verhalten.
Profilname enthält Punkte.\nDies wird von NS nicht unterstützt.\nProfil wird nicht zu NS hochgeladen. Unterer Wert des Zielbereichs (nur Anzeige) Oberer Wert des Zielbereichs (nur Anzeige) - Alter: - Gewicht: + Alter + Gewicht ID: Senden Meistgenutztes Profil: @@ -900,9 +900,41 @@ Unerwartetes Verhalten. Fehler Hochladen verlangsamen Status BZ-Daten + Kanülenalter + Alter Patchpumpe + Patch-Pumpe Verwendete Daten neu berechnet BZ zu nah:\n%1$s\n%2$s Identifikation (E-Mail, Facebook oder Discord Nickname) Identifikation im Dev-Modus nicht gesetzt + Dialog + Aktueller Blutzucker + korrektes Ergebnis mit % + korrektes Ergebnis mit Einheiten Nicht verfügbar + hoch + im Zielbereich + niedrig + schnell fallend + fallend + langsam fallend + stabil + Langsamer Anstieg + steigend + schnell steigend + kein(e) + unbekannt + Diagramm + BZ-Qualität + neu berechnet + doppelte Einträge + Insulin + Blutzucker + veraltet + Erinnerung einstellen + Neues Profil hinzufügen + aktuelles Profil klonen (kopieren) + aktuelles Profil löschen + neu zur Liste hinzufügen + diff --git a/app/src/main/res/values-el-rGR/strings.xml b/app/src/main/res/values-el-rGR/strings.xml index 22f1ed8d55..65cd30fa60 100644 --- a/app/src/main/res/values-el-rGR/strings.xml +++ b/app/src/main/res/values-el-rGR/strings.xml @@ -183,7 +183,6 @@ Wear Ξαναστείλτε όλα τα Δεδομένα Ρυθμίσεις στο Wear - Βασικός Ρυθμός: Τιμή βασικού κάτω από το ελάχιστο. Δεν έχει ρυθμιστεί το προφίλ! BG: Τελευταία BG: @@ -578,4 +577,5 @@ %1$d%% min + diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index 56d720ff94..826b04dfd7 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -25,6 +25,7 @@ Sincroniza tus datos con Nightscout Estado del algoritmo en 2017 Algoritmo más reciente para usuarios avanzados + Algoritmo más reciente para usuarios avanzados con ISF dinámico/automático Muestra el estado actual de tu lazo y los botones para las acciones más usadas Muestra una notificación en curso con un breve resumen de lo que está haciendo tu lazo Define un perfil que esté disponible cuando tengas una desconexión @@ -224,7 +225,7 @@ Validar: Añadir Editar - BOLO + COMIDA Corrección Acciones (PELIGROSO DESHABILITAR) Sólo subida a Nightscout @@ -246,7 +247,7 @@ Reloj Reenviar todos los datos Abrir ajustes en el reloj - Ratio Basal: + Tasa Basal Valor basal por debajo del mínimo. Perfil no establecido. Glucosa: Última Glucosa: @@ -267,6 +268,7 @@ CONF LAZO OAPS + DYNISF PERFIL INICIO BOMBAV @@ -434,6 +436,7 @@ Habilita las transmisiones a otras aplicaciones (como xDrip+). ¡No lo habilites si tienes más de una instancia de AAPS o NSClient instaladas! Habilitar la emisión de mensajes localmente. OpenAPS SMB + OpenAPS SMB ISF Dinámico Activar UAM Activar SMB Usar microbolos en lugar de basales temporales, para corregir más rápidamente @@ -502,6 +505,7 @@ Solo negativo Cálculo COB Cálculo objetivo temporal + Cálculo de porcentaje Lazo activado APS seleccionado NSClient tiene permiso para escribir @@ -757,8 +761,8 @@ El nombre de perfil contiene puntos.\nEsto no está soportado por NS.\nEl perfil no se carga en NS. Valor de glucosa baja (sólo visualización) Valor de glucosa alta (sólo visualización) - Edad: - Peso: + Edad + Peso ID: Enviar Perfil más común: @@ -900,9 +904,74 @@ Errores Ralentizar subidas Estado de datos de glucosa + edad de la cánula + edad del parche de la bomba + Bomba parche Datos recalculados utilizados Datos de glucosa demasiado cercanos:\n%1$s\n%2$s Identificación (correo electrónico, FB, nick de Discord, etc.) Identificación no establecida en el modo dev + diálogo + glucosa en sangre actual + resultado correcto con % + corregir resultado con unidades No disponible + alto + en rango + bajo + bajando rápido + bajando + bajando despacio + estable + subiendo despacio + subiendo + subiendo rápido + ninguno + desconocido + gráfico + calidad de glucosa en sangre + recalculado + entradas dobles + insulina + glucosa en sangre + desactualizado + establecer recordatorio + añadir nuevo perfil + clonar el perfil actual + borrar el perfil actual + añadir nuevo a la lista + + Objetivo Temporal preestablecido desconocido: %1$s + ¿Cancelar la ejecución del objetivo temporal? + ¡Diferentes unidades usadas en reloj y en el teléfono! + Objetivo Temporal Zero - ¿Cancelar el Objetivo Temporal en ejecución? + ¡Glucosa mínima fuera de rango! + ¡Glucosa máxima fuera de rango! + Objetivo temporal:\nMin: %1$s\nMax: %2$s\nDuración: %3$s + Objetivo temporal:\nObjetivo: %1$s\nDuración: %2$s + ObjetivoTemporal:\Razón: %1$s\nObjetivo: %2$s\nDuración: %3$s + Asistente Rápido: %1$s\nInsulina: %2$.2fU\nCarbohidratos: %3$dg + Calc. Asistente:\nInsulina: %1$.2fU\nCarbohidratos: %2$dg + Mostrar entrada en dispositivo: + El asistente rápido seleccionado ya no está disponible, por favor actualice su mosaico + ¡No hay valor de glucosa reciente en el que basar el cálculo! + ¡No hay perfil activo! + COB desconocido! ¿Valor de glucosa ausente o reincio reciente de la aplicación? + ¡Violación de restricción de carbohidratos! + Calc (CI: %2$.1f, ISF: %2$.1f) desde:\" + Carbohidratos: %1$.2fU + COB: %1$.0fg %2$.2fU + BG: %1$.2fU + Basal IOB: %1$.2fU + Bolo IOB: %1$.2fU + Superbolo: %1$.2fU + Tendencia 15\': %1$.2fU + Porcentaje: %1$.2fU x %2$d%% ≈ %3$.2fU + ¡Violación de restricciones de insulina!\nNo se puede entregar %1$.2fU + BasalT: %1$s + %1$s a %2$s + ¡No hay bomba disponible! + Comando de acción desconocido: + Porcentaje + Aplicación por defecto diff --git a/app/src/main/res/values-fr-rFR/strings.xml b/app/src/main/res/values-fr-rFR/strings.xml index 52aec3ac4c..c71b5a031a 100644 --- a/app/src/main/res/values-fr-rFR/strings.xml +++ b/app/src/main/res/values-fr-rFR/strings.xml @@ -247,7 +247,7 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S Wear Renvoyer toutes les données Afficher les Paramètres sur la Montre - Débit Basal : + Débit de Basal Le débit Basal est inférieur au minimum autorisé. Profil non accepté ! G: Dernière G: @@ -503,6 +503,7 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S Seulement négatif Calcul GA Cible temporaire + Calcul du pourcentage Boucle activée APS Sélectionné NSClient a la permission d\'écriture @@ -758,8 +759,8 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S Le nom du profil contient des points.\nCe n\'est pas pris en charge par NS.\nLe profil n\'est pas remonté dans NS. Valeur inférieure dans la plage (affichage uniquement) Valeur supérieure dans la plage (affichage uniquement) - Âge : - Poids : + Âge  + Poids  ID : Envoyer Profil le plus courant : @@ -900,9 +901,74 @@ L\'ENSEMBLE DES RISQUES LIÉS À LA QUALITÉ ET À LA PERFORMANCE DU PROGRAMME S Erreurs Ralentir les téléchargements État des données Gly + âge canule + âge pompe patch + Pompe patch Données recalculées utilisées Gly trop proche :\n%1$s\n%2$s Identification (email, FB ou pseudo dans Discord, etc) Identification non définie en mode dev + dialogue + glycémie actuelle + corriger le résultat avec le % + corriger le résultat avec les unités Non disponible + haut + dans la plage + bas + en baisse rapide + en baisse + en baisse lente + stable + en hausse lente + en hausse + en hausse rapide + aucun + inconnu + graphique + qualité de la glycémie + recalculé + entrées doubles + insuline + glycémie + obsolète + définir un rappel + ajouter un nouveau profil + dupliquer le profil actuel + supprimer le profil actuel + ajouter un nouveau à la liste + + Préréglage inconnu de la cible temporaire : %1$s + Annuler l\'exécution des cibles Temp? + Différentes unités utilisées sur la montre et le téléphone! + Pas de Cible Temp - annuler la cible temporaire en cours? + Gly mini hors limite! + Gly maxi hors limite! + Cible temporaire:\nMin: %1$s\nMax : %2$s\nDurée : %3$s + Cible temporaire:\nCible: %1$s\nDurée: %2$s + Cible temporaire:\nRaison: %1$s\nCible : %2$s\nDurée : %3$s + Assistant: %1$s\nInsuline : %2$.2fU\nGlucides : %3$dg + Assistant Calc :\nInsuline : %1$.2fU\nGlucides : %2$dg + Afficher l\'entrée sur l\'appareil : + L\'assistant rapide sélectionné n\'est plus disponible, veuillez actualiser l\'écran + Pas de glycémie récente pour calculer ! + Aucun profil activé ! + GA inconnu! glycémie manquante ou démarrage récent de l\'application ? + Violation de contrainte des glucides! + Calcul (G/I: %2$.1f, SI: %2$.1f) de:\" + Glucides : %1$.2fU + GA: %1$.0fg %2$.2fU + Gly: %1$.2fU + Basal IA: %1$.2fU + Bolus IA: %1$.2fU + Superbolus : %1$.2fU + tendance 15\': %1$.2fU + Pourcentage : %1$.2fU x %2$d%% ≈ %3$.2fU + Violation de contrainte d\'insuline!\nImpossible de délivrer %1$.2fU + Cible Temp: %1$s + %1$s vers %2$s + Aucune pompe disponible! + Commande inconnue : + Pourcentage + Application par défaut diff --git a/app/src/main/res/values-ga-rIE/strings.xml b/app/src/main/res/values-ga-rIE/strings.xml index db1151a6be..e8366c934a 100644 --- a/app/src/main/res/values-ga-rIE/strings.xml +++ b/app/src/main/res/values-ga-rIE/strings.xml @@ -78,7 +78,6 @@ Aonaid: Aonaid DIA - Bunaidh ráta: BG: GF deiridh: MDI @@ -186,7 +185,7 @@ DIA IC ISF - Aois: BG + diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index e1cca72b48..7d6d176357 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -5,4 +5,5 @@ WiFi SSID + diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index 21a1138cae..a8da25a5d0 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -246,7 +246,6 @@ Smartwatch Invia di nuovo tutti i dati Apri impostazioni sullo smartwatch - Velocità basale: Valore basale inferiore al minimo. Profilo non impostato! BG: Ultimo BG: @@ -757,8 +756,6 @@ Il nome profilo contiene dei punti.\nQuesto non è supportato da NS.\nIl profilo non viene caricato in NS. Valore più basso per l\'intervallo di visualizzazione dell\'area \"in range\" Valore più alto per l\'intervallo di visualizzazione dell\'area \"in range\" - Età: - Peso: ID: Invia Profilo più comune: @@ -905,4 +902,5 @@ Identificazione (email, nick Discord o FB, etc) Identificazione non impostata in modalità dev Non disponibile + diff --git a/app/src/main/res/values-iw-rIL/strings.xml b/app/src/main/res/values-iw-rIL/strings.xml index 9638fe5425..be7004a3b6 100644 --- a/app/src/main/res/values-iw-rIL/strings.xml +++ b/app/src/main/res/values-iw-rIL/strings.xml @@ -25,6 +25,7 @@ מסנכרן את נתוניכם עם Nightscout הישאר עם האלגוריתם של 2017 האלגוריתם העדכני ביותר, עבור משתמשים מתקדמים בלבד + האלגוריתם העדכני ביותר, נועד למשתמשים מתקדמים עם רגישות (ISF) דינאמית\\אוטומטית מציג את המצב הנוכחי של הלולאה ולחצני פעולות שימושיות מציג הודעה קבועה עם סקירה קצרה של מה שהלולאה שלכם עושה הגדירו פרופיל שזמין באופן לא מקוון. @@ -246,7 +247,6 @@ Wear שלח מחדש את כל הנתונים פתיחת הגדרות Wear - מינונים בזאליים: ערך הבסיס מתחת למינימום. פרופיל אינו מוגדר! ערכי סוכר בדם: ערכי סוכר אחרונים: @@ -260,13 +260,14 @@ מערך של %1$d אלמנטים. \n ערך נוכחי: נתוני חישוב רגישות אוטו\' תיקון באגים בסקריפט - אפשר חישוב רגישות אוטומטית (Autosens) + אפשר חישוב רגישות אוטומטי (Autosens) רענון אירועים מנייטסקאוט מחיקת טיפולים עתידיים ACT CONF לולאה OAPS + DynISF LP בית VPUMP @@ -280,8 +281,8 @@ פרופיל ערך ברירת מחדל: 3 מנגנון הגנה עיקרי של OpenAPS. מגביל את המינון הבזאלי לעד פי 3 מהמינון הבזאלי הגבוה ביותר שהוגדר. ברוב המקרים אין צורך לשנות ערך זה, אך יש לזכור שזו המשמעות של “3x max daily; 4x current” בדיון על מנגנוני הגנה. ערך ברירת מחדל: 4 זהו החצי השני של מנגנון הגנה עיקרי של OpenAPS, והחצי השני של \"3x max daily; 4x current\" במנגנוני ההגנה. המשמעות היא שהמינון הבזאלי, ללא קשר למקסימום שנקבע במשאבה, אינו יכול להיות גבוה יותר ממספר זה כפול הקצב הבזאלי הנוכחי. מיועד למנוע כניסה לתחומים מסוכנים ע\"י קביעת קצב בזאלי גבוה לפני הבנה של פעולת האלגוריתם. שוב: ברירת המחדל היא x4, רוב המשתמשים לעולם אינם צריכים לשנות ערך זה ואם הם מרגישים שמנגנון הגנה זה מפריע להם, הפתרון הוא בשינוי של הגדרות אחרות. - ערך ברירת מחדל: 1.2\nזוהי מגבלת המכפיל של autosens (ובקרוב autotune) שמגדירה 20%% כיחס מקסימלי של autosens, אשר קובע בתורו את גובה הבזאלי המקסימלי, גובהו המינימלי של יחס התיקון, ואת המינימום של ערכי המטרה האפשריים. - ערך ברירת מחדל: 0.7\nבצד השני של מגבלות הבטיחות של autosens, ערך זה מגביל את יכולתו של autosens להוריד את הערכים הבזאליים ועד כמה יכול להעלות את יחס התיקון ואת ערכי מטרת הסוכר בדם. + ערך ברירת מחדל: 1.2\nזוהי מגבלת המכפיל של Autosens (ובקרוב Autotune) שמגדירה 20% כיחס מקסימלי של autosens, אשר קובע בתורו את גובה הבזאלי המקסימלי, גובהו המינימלי של יחס התיקון, ואת המינימום של ערכי המטרה האפשריים. + ערך ברירת מחדל: 0.7\nבצד השני של מגבלות הבטיחות של Autosens, ערך זה מגביל את יכולתו של autosens להוריד את הערכים הבזאליים ועד כמה יכול להעלות את יחס התיקון ואת ערכי מטרת הסוכר בדם. וויסות ערכי מטרה ע\"י Autosens ערך ברירת מחדל: התאמה מדויקת\n נועד לאפשר ל-Autosens לשנות את המטרה של ערכי הסוכר, בנוסף ליחס התיקון והבזאלים. ערך ברירת מחדל: 2\n מעכב בולוס מופעל אחרי שאתם מזריקים בולוס ארוחה, כך שהלולאה לא תפצה ע\"י בזאלי זמני נמוך אחרי הארוחה. הדוגמה כאן וברירת המחדל היא 2; כך שהגדרה של משך פעילות אינסולין של 3 שעות משמעה שהעיכוב יחלוף בהדרגה בתוך 1.5 שעות (3 ש\' לחלק ל-2). @@ -434,6 +435,7 @@ אפשר הפצה לאפליקציות אחרות (כגון xDrip). אין להפעיל אם מותקן לכם יותר ממופע אחד של AAPS או NSClient! אפשר שידורים מקומיים. OpenAPS SMB + OpenAPS SMB רגישות דינאמית הפעלת UAM אפשר SMB השתמש בסופר מיקרו בולוסים במקום בבזאלי זמני לפעילות מהירה יותר @@ -757,8 +759,6 @@ שם הפרופיל מכיל נקודות.\nשם כזה אינו נתמך ע\"י Nightscout \n הפרופיל לא הועלה ל-Nightscout. ערך נמוך יותר באזור הטווח (הצגה בלבד) ערך גבוה יותר באזור הטווח (הצגה בלבד) - גיל: - משקל: מס\' זיהוי: עדכן הפרופיל הנפוץ ביותר: @@ -900,9 +900,36 @@ שגיאות האט העלאות מצב נתוני הסוכר + גיל הצינורית + גיל משאבה + משאבה ללא צינורית משתמש בנתונים מחושבים מחדש רמת הסוכר קרובה מדי:\n%1$s\n%2$s אמצעי זיהוי (מייל, פייסבוק או דיסקורד וכו\') אמצעי הזיהוי אינו מוגדר במצב מפתחים + תיבת דו-שיח + רמת סוכר נוכחית + תיקון עם % + תיקון עם יחידות לא זמין + גבוה + בטווח + נמוך + ירידה מהירה + ירידה + ירידה איטית + יציב + עלייה איטית + עלייה + עלייה מהירה + אין + לא ידוע + גרף + איכות נתוני סוכר + חושב מחדש + רישומים כפולים + אינסולין + ערכי סוכר בדם + לא עדכני + diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index 4c44ebc5a0..c90ae33577 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -242,7 +242,6 @@ 워치 모든 데이터 다시 보내기 워치에서 설정 열기 - Basal양: Basal값이 최소값 이하입니다. 프로파일이 설정되지 않습니다! BG: Last BG: @@ -738,8 +737,6 @@ 프로파일명에 점을 포함하고 있습니다.\n이는 NS에서 지원하지 않습니다.\n프로파일이 NS에 업로드되지 않습니다. 혈당 정상범위의 하한값(표시 전용) 혈당 정상범위의 상한값(표시 전용) - 나이: - 몸무게: ID: 확인 가장 많이 사용된 프로파일: @@ -860,4 +857,5 @@ 직전의 펌프 통신 종료를 기다리는 동안 타임 아웃 대기열에 또다른 bolus가 있습니다. 이후에 다시 시도하세요. 계산 진행 중 + diff --git a/app/src/main/res/values-lt-rLT/strings.xml b/app/src/main/res/values-lt-rLT/strings.xml index 7ea144c397..cfb0725dcb 100644 --- a/app/src/main/res/values-lt-rLT/strings.xml +++ b/app/src/main/res/values-lt-rLT/strings.xml @@ -246,7 +246,6 @@ Išmanieji laikrodžiai Pakartotinai siųsti visus duomenis Atidaryti išmaniojo laikrodžio nustatymus - Valandinė bazė: Valandinės bazės vertė mažesnė už minimalią. Profilis nenustatytas! KG: Paskutinė KG: @@ -757,8 +756,6 @@ Profilio pavadinime yra taškų.\nŠios funkcijos NS nepalaiko.\nProfilis neįkeltas į NS. Mažiausia tikslinės srities vertė (tik rodymui) Didžiausia tikslinės srities vertė (tik rodymui) - Amžius: - Svoris: ID: Pateikti Dažniausiai naudojamas profilis: @@ -904,4 +901,5 @@ Identifikacija (el. paštas, FB, Discord slapyvardis ar kt.) Kūrėjo režime tapatybė nenustatyta Negalimas + diff --git a/app/src/main/res/values-nl-rNL/strings.xml b/app/src/main/res/values-nl-rNL/strings.xml index 382ab43d7b..69ce798126 100644 --- a/app/src/main/res/values-nl-rNL/strings.xml +++ b/app/src/main/res/values-nl-rNL/strings.xml @@ -25,6 +25,7 @@ Synchroniseert je data met Nightscout Het algoritme uit 2017 Meest recente algoritme voor gevorderde gebruikers + Meest recente algoritme voor gevorderde gebruikers met dynamische/automatische ISF Toont de huidige Loop-status en knoppen voor meest gebruikte acties Toont een permanente melding met een beknopt overzicht van hetgeen de Loop momenteel doet Gebruik profiel(en) die je in AAPS aanmaakt en offline kunt gebruiken. @@ -246,7 +247,7 @@ Wear Update Wear gegevens Open instellingen op Wear - Basaal: + Basaalstand Basaalwaarde onder minimum. Profiel niet ingesteld! BG: Laatste BG: @@ -434,6 +435,7 @@ Schakel lokaal data delen met andere apps (zoals xDrip) in. Schakel dit niet in als er meer dan één installatie van AAPS of NSClient zijn geinstalleerd! Activeer locaal delen. OpenAPS SMB + OpenAPS SMB Dynamische ISF Activeer UAM Activeer SMB SMB in plaats van tijdelijke basalen voor snellere reactie @@ -502,6 +504,7 @@ Enkel negatief COB berekening Tijdelijk doel berekenen + Percentage berekening Loop Actief APS geslecteerd NSClient heeft schrijf rechten @@ -757,8 +760,8 @@ Profielnaam bevat punten.\nDit wordt niet ondersteund door NS.\nProfiel is niet geüpload naar NS. Laagste waarde in bereik (alleen weergave) Hoogste waarde in bereik (alleen weergave) - Leeftijd: - Gewicht: + Leeftijd + Gewicht ID: Verzenden Meest voorkomende profiel: @@ -900,9 +903,74 @@ Foutmeldingen Vertraag uploads BG data status + canule leeftijd + patchpomp leeftijd + Patchpomp Herberekende data gebruikt BG data interval to kort:\n%1$s\n%2$s Identificatie (e-mail, FB, Discord e. d.) Identificatie niet ingesteld in dev modus + dialoogvenster + huidige bloedglucose + corrigeer uitkomt met percentage + corrigeer uitkomt met units Niet beschikbaar + hoog + binnen bereik + laag + snel dalend + dalend + langzaam dalend + stabiel + langzaam stijgend + stijgt + snel stijgend + geen + onbekend + grafiek + bloedglucose kwaliteit + opnieuw berekend + dubbele items + insuline + bloed glucose + verouderd + herinnering instellen + nieuw profiel toevoegen + huidig profiel dupliceren + huidig profiel verwijderen + nieuwe toevoegen aan lijst + + Tijdelijke doel onbekende preset: %1$s + Huidige tijdelijk streefdoel annuleren? + Verschillende eenheden gebruikt op horloge en telefoon! + Tijdelijk streefdoel 0 minuten, huidige tijdelijk streefdoel annuleren? + Min BG buiten bereik! + Max BG buiten bereik! + Tijdelijk streefdoel:\nMin: %1$s\nMax: %2$s\nDuur: %3$s + Tijdelijk streefdoel:\nDoel: %1$s\nDuur: %2$s + Tijdelijk streefdoel:\Reden: %1$s\nDoel: %2$s\nDuur: %3$s + QuickWizard: %1$s\nInsuline: %2$.2fE\nKoolhy.: %3$dg + Reken. Wizard:\nInsuline: %1$.2fE\nKoolhy.: %2$dg + Toon invoer op apparaat: + Geselecteerde QuickWizard is niet meer beschikbaar, vernieuw uw tegel + Geen recente BG om de berekening op te baseren! + Geen actief profiel ingesteld! + Onbekende COB! BG uitlezing ontbreekt of de recente app herstart? + Koolhydraten beperking overschreden! + Bereken (IC: %2$.1f, ISF: %2$.1f) van:\" + Koolhydraten: %1$.2fE + COB: %1$.0fg %2$.2fE + BG: %1$.2fE + Basaal IOB: %1$.2fE + Bolus IOB: %1$.2fE + Superbolus: %1$.2fE + 15\' trend: %1$.2fE + Percentage: %1$.2fE x %2$d%% ≈ %3$.2fE + Insuline beperking!\nKan %1$.2fE niet leveren + Tijdelijk Doel: %1$s + %1$s tot %2$s + Geen pomp beschikbaar! + Onbekend actie commando: + Percentage + Applicatie standaardwaarden diff --git a/app/src/main/res/values-no-rNO/strings.xml b/app/src/main/res/values-no-rNO/strings.xml index 738dcf2a4c..0732ae1dbd 100644 --- a/app/src/main/res/values-no-rNO/strings.xml +++ b/app/src/main/res/values-no-rNO/strings.xml @@ -25,6 +25,7 @@ Synkroniserer dine data med Nightscout Slik algoritmen var definert i 2017 Siste utgave av algoritmen for avanserte brukere + Nyeste algoritme for avanserte brukere med dynamisk/automatisk ISF Viser loopens nåværende tilstand og knapper for de vanligste funksjonene Viser en konstant melding med en kort oppsummering av hva loop gjør Definer en profil som er tilgjengelig offline. @@ -246,7 +247,7 @@ Klokke Send alle data på nytt Åpne Innstillinger på klokken - Basal rate: + Basal rate Basal verdi under minimum. Profilen settes ikke! BS: Siste BS: @@ -267,6 +268,7 @@ KONF LOOP OAPS + DYNISF LP HJEM VPUMP @@ -434,6 +436,7 @@ Aktiver kringkasting til andre apper (som xDrip+). Ikke aktiver dette hvis du har mer enn en AAPS eller NSClient installert! Aktiver lokale sendinger. OpenAPS SMB + OpenAPS SMB dynamisk ISF Aktiver UAM Aktiver SMB Bruk Super Mikro Solen i stedet for temp basal for raskere resultat @@ -502,6 +505,7 @@ Bare negative COB beregning Temp target beregning + Prosent beregning Loop er aktivert APS valgt NSClient har skrive rettigheter @@ -757,8 +761,8 @@ Profilnavnet inneholder prikker.\nDette støttes ikke av NS.\nProfilen er ikke lastet opp til NS. Nedre verdi for målområdet (kun visning) Øvre verdi for målområdet (kun visning) - Alder: - Vekt: + Alder + Vekt ID: Lagre Mest vanlig profil: @@ -900,9 +904,74 @@ Feil Reduser opplastingshastighet BS data status + kanyle alder + patch pumpe alder + Patch pumpe Rekalkulerte siste data BS for nær:\n%1$s\n%2$s Identifikasjon (e-post, Facebook eller Discord nick osv.) Identifikasjon ikke satt i utviklermodus + dialogvindu + nåværende blodsukker + korriger resultatet med % + korriger resultatet med enheter Ikke tilgjengelig + høy + i målområdet + lav + synker raskt + synker + synker sakte + stabil + stiger sakte + stiger + stiger raskt + ingen + ukjent + graf + blodsukkermålingens kvalitet + beregnet på nytt + doble registreringer + insulin + blodsukker + utdatert + angi påminnelse + legg til ny profil + kopier gjeldende profil + slett gjeldende profil + legg til ny i liste + + Temptarget ukjent forhåndsinnstilling: %1$s + Avbryt gjeldende Temp Target? + Forskjellige enheter brukt på klokke og telefon! + Zero-TempTarget - avbryter gjeldende TempTarget? + Min-BS utenfor område! + Maks-BS utenfor område! + Temp target:\nMin: %1$s\nMaks: %2$s\nVarighet: %3$s + TempTarget:\nMål: %1$s\nVarighet: %2$s + TempTarget:\nMin: %1$s\nMål: %2$s\nVarighet: %3$s + QuickWizard: %1$s\ninsulin: %2$.2fE\nKarbo: %3$dg + Kalk. Wizard:\nInsulin: %1$.2fE\nKarbo: %2$dg + Vis oppføring på enhet: + Den valgte hurtigveiviseren er ikke tilgjengelig lenger, oppdater klokkewidget + Mangler nylige BS verdier til å bruke i beregninger! + Det er ikke angitt noen aktiv profil! + Ukjent COB! BS verdier mangler eller nylig oppstart av appen? + Brudd på karbo begrensning! + Kalk (IC: %2$.1f, ISF: %2$.1f) fra:\" + Karbo: %1$.2fE + COB: %1$.0fg %2$.2fE + BS: %1$.2fE + Basal IOB: %1$.2fE + Bolus IOB: %1$.2fE + Superbolus: %1$.2fE + 15\' trend: %1$.2fE + Prosent: %1$.2fE x %2$d%% ° %3$.2fE + Insulinbegrensning nådd!\nKan ikke levere %1$.2fE + TempT: %1$s + %1$s til %2$s + Ingen pumpe tilgjengelig! + Ukjent kommando: + Prosent + Standardverdi diff --git a/app/src/main/res/values-pl-rPL/strings.xml b/app/src/main/res/values-pl-rPL/strings.xml index 6188c8d78a..55b0b01565 100644 --- a/app/src/main/res/values-pl-rPL/strings.xml +++ b/app/src/main/res/values-pl-rPL/strings.xml @@ -246,7 +246,6 @@ Oprogramowanie Wear (Smartwatch) Prześlij ponownie wszystkie dane Otwórz ustawienia dla Wear - Dawka bazowa: Wartość bazy poniżej minimum. Nie ustawiono profilu! BG: Ostatnia BG: @@ -757,8 +756,6 @@ Nazwa profilu zawiera kropki.\nTo nie jest obsługiwane przez NS.\nProfil nie zostanie przesyłany do NS. Dolna wartość zakresu docelowego (tylko do wyświetlania) Górna wartość zakresu docelowego (tylko do wyświetlania) - Czas: - Waga: ID: Wyślij Najczęściej używany profil: @@ -904,4 +901,5 @@ Identyfikator (email, nick na FB lub Discordzie itp.) Identyfikator nie jest ustawiony w trybie dev Niedostępne + diff --git a/app/src/main/res/values-pt-rBR/exam.xml b/app/src/main/res/values-pt-rBR/exam.xml index d6a0e2b230..a41cf854b0 100644 --- a/app/src/main/res/values-pt-rBR/exam.xml +++ b/app/src/main/res/values-pt-rBR/exam.xml @@ -32,11 +32,12 @@ Seu arquivo de configurações foi encontrado no armazenamento interno/AAPS/preferências do seu telefone. Copie seu arquivo de preferências para um local seguro fora de seu telefone (por exemplo, usando uma unidade na nuvem, conectando um cabo a um computador, e-mail, etc.) Se seu telefone ficar danificado ou se você perder-lo, existem maneiras fáceis de recuperar suas configurações remotamente sem um backup local. + Leituras do CGM imprecisas O que deve ser feito se os dados do CGM são irregulares? Se os níveis de glicose no sangue estiverem fora dos limites aceitáveis (muito baixo ou muito alto) a calculadora de bolus pode ser usada para fornecer sugestões para correções de carboidrato ou insulina. https://androidaps.readthedocs.io/en/latest/EN/Getting-Started/FAQ.html#insulin-to-carb-ratio-ic-g-u Tópico: e-Carbs - Para que você possa usar os e-Carbs (carboidratos estendidos)? + Para que você possa usar os e-carbs (carboidratos estendidos)? Para agendar carboidratos no futuro, possivelmente distribuídos num intervalo (semelhante a um bolus estendido que distribui insulina num intervalo). Para registrar carboidratos de exercício \'gratuitos\' que deseja ocultar do AndroidAPS. Os e-carbs (distribuídos no futuro) podem ajudar o AndroidAPS a lidar com comidas ricas em gorduras/proteínas. @@ -51,7 +52,7 @@ https://androidaps.readthedocs.io/en/latest/EN/Children/Children.html Tópico: Fator de Sensibilidade à Insulina (ISF) Aumentar os valores de ISF levará à administração de mais insulina para cobrir uma quantidade específica de carboidratos. - Reduzir os valores do ISF levará à adminstração de quantidades menores de insulina para corrigir uma glicose acima do alvo. + Reduzir os valores do ISF levará à adminstração de quantidades maiores de insulina para corrigir uma glicose acima do alvo. Aumentar ou reduzir o ISF não tem efeito na administração de insulina quando os níveis de glicose estão abaixo do alvo. O ISF deve ser configurado nas Preferências do AndroidAPS. Alterar o valor do ISF no seu perfil é o suficiente para aplicar a alteração. @@ -59,7 +60,6 @@ https://androidaps.readthedocs.io/en/latest/EN/Usage/Profiles.html Você pode definir mais do que um valor para o rácio I:C no seu perfil. Se você mudar o ISF no seu perfil, também deveria mudar o I:C. - Tópico: Rácio Insulina:Carboidrato (racio I:C) Rácios IC mais altos levam a menos insulina administrada por uma dada quantidade de carboidratos. Rácios IC mais baixos levam a menos insulina administrada por uma dada quantidade de carboidratos. Se tiver 0 COB, alterar a proporção IC irá levar a uma quantidade diferente de insulina para corrigir um determinado valor da glicemia. @@ -70,8 +70,7 @@ Ao especificar uma mudança de perfil de 90%, quais respostas são corretas? Taxas de basal serão 10% menores. O valor do ISF será 10% maior. - O valor da proporção I:C será 10% menor. - O ISF e a I:C continuem iguas. + O ISF e a I:C não sofrem alterações. https://androidaps.readthedocs.io/en/latest/EN/Usage/Profiles.html?highlight=profile%20switch#profile-switch Tópico: Troca de Perfil https://androidaps.readthedocs.io/en/latest/EN/Usage/Profiles.html?highlight=profile%20switch#timeshift diff --git a/app/src/main/res/values-pt-rBR/objectives.xml b/app/src/main/res/values-pt-rBR/objectives.xml index 39013b9366..bca5eb5aee 100644 --- a/app/src/main/res/values-pt-rBR/objectives.xml +++ b/app/src/main/res/values-pt-rBR/objectives.xml @@ -1,5 +1,7 @@ + Entendendo o seu loop aberto, incluindo as suas recomendações de basais temporárias + Com base nessa experiência, decidir qual deve ser a basal máximo e configurá-lo na bomba e nas preferências Leia os documentos de como a automação funciona. Configure suas primeiras regras simples. Em vez de efetuar uma ação deixe AAPS apresentar apenas uma notificação. Quando você tiver certeza de que a automação é acionada no momento certo substitua a notificação por uma ação real. (https://androidaps.readthedocs.io/en/latest/EN/Usage/Automation.html) Glicose disponível no NS Status da Bomba disponível no NS diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index ed13248a9e..89743a1cbb 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -217,7 +217,6 @@ Wear Reenviar Todos os Dados Abrir Definições em Wear - Valor da Basal: Valor da basal abaixo do mínimo. Perfil não definido! BG: Último BG: @@ -656,7 +655,6 @@ Nome do perfil contém pontos.\nIsso não é suportado pelo NS.\nPerfil não foi enviado para o NS. Valor mais baixo da área de intervalo (apenas exibição) Valor mais alto da área de intervalo (apenas exibição) - Idade: Enviar Perfil mais comum: Nota: Apenas os dados visíveis neste ecrã serão enviados anonimamente. O ID é atribuído a esta instalação do AndroidAPS. Você pode enviar dados novamente se o perfil principal for alterado, mas deixá-lo rodar pelo menos uma semana para tornar o resultado visível no intervalo de tempo. Sua ajuda é apreciada. @@ -705,4 +703,5 @@ Botões são sempre exibidos na parte inferior da tela Mostrador Grande Tema + diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 754acafe9a..6f39d90a8a 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -246,7 +246,6 @@ Wear Reenviar Todos os Dados Abrir Definições no Relógio - Taxa da Basal: Valor da basal abaixo do mínimo. Perfil não definido! Glicose: Ultima Gli: @@ -757,8 +756,6 @@ Nome do perfil contém pontos.\nIsso não é suportado pelo NS.\nPerfil não é enviado para o NS. Valor mais baixo da área de intervalo (apenas exibição) Valor mais alto da área de intervalo (apenas exibição) - Idade: - Peso: ID: Enviar Perfil mais comum: @@ -905,4 +902,5 @@ Identificação (e-mail, nick FB ou Discord, etc) Identificação não definida no modo desenvolvimento Indisponível + diff --git a/app/src/main/res/values-ro-rRO/strings.xml b/app/src/main/res/values-ro-rRO/strings.xml index 12ec6b9803..385e6ab60b 100644 --- a/app/src/main/res/values-ro-rRO/strings.xml +++ b/app/src/main/res/values-ro-rRO/strings.xml @@ -246,7 +246,6 @@ Ceas Retrimite toate datele Deschide setările pe Wear - Rată bazală: Valoarea bazalei este sub minimul permis. Profilul nu este setat! Glicemie: Ultima glicemie: @@ -757,8 +756,6 @@ Numele profilului conține puncte.\nAcest lucru nu este permis de NS.\nProfilul nu a fost înregistrat în NS. Valoarea inferioară a intervalului țintă (doar afișare) Valoarea superioară a intervalului țintă (doar afișare) - Vârstă: - Greutate: ID: Trimiteți Cel mai frecvent profil: @@ -905,4 +902,5 @@ Identificare (email, FB sau Discord etc) Identificarea nu este setată în modul dezvoltator Nu este disponibil + diff --git a/app/src/main/res/values-ru-rRU/strings.xml b/app/src/main/res/values-ru-rRU/strings.xml index 8c71e3541a..7bb151d4fd 100644 --- a/app/src/main/res/values-ru-rRU/strings.xml +++ b/app/src/main/res/values-ru-rRU/strings.xml @@ -246,7 +246,6 @@ Смарт-часы Wear повторить отправку всех данных Открыть настройки на Wear - Шаг базала: значение базала ниже минимума. профиль не создан! гликемия: прошлый СК: @@ -757,8 +756,6 @@ Имя профиля содержит точки.\nЭто не поддерживается NS.\nПрофиль не выгружен в NS. Меньшее значение диапазона целевых значений (только для дисплея) Большее значение диапазона целевых значений (только для дисплея) - Возраст: - Вес: Идентификатор: Отправить Наиболее часто применяемый профиль: @@ -899,9 +896,36 @@ Ошибки Замедлить выгрузку Состояние данных ГК + время, отработанное катетером помпы + время отработанное разовой помпой + Разовая помпа Используются пересчитанные данные ГК слишком близко к \n%1$s\n%2$s Идентификация (электронная почта, ник в Facebook или Discord и т. п) Идентификация не задана в режиме разработчика + диалог + текущий уровень гликемии + корректный результат в % + корректный результат в ед Недоступно + высокий + в диапазоне + низкий + быстро падает + падает + медленно падает + стабильный + медленно поднимается + растет + стремительно растет + отсутствует + неизвестно + график + качество глюкозы в крови + пересчитано + двойные записи + инсулин + уровень глюкозы в крови (ГК) + устаревшие данные + diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml index 3b208c5744..9dbf3f2944 100644 --- a/app/src/main/res/values-sk-rSK/strings.xml +++ b/app/src/main/res/values-sk-rSK/strings.xml @@ -25,6 +25,7 @@ Synchronizuje vaše dáta s NS Stav algoritmu v roku 2017 Najnovší algoritmus pre pokročilých užívateľov + Najnovší algoritmus pre pokročilých užívateľov s dynamickým/automatickým ISF Zobrazenie aktuálneho stavu vašeho uzavretého okruhu a tlačidlá k najpoužívanejším ovládacím prvkom Zobrazuje priebežné oznámenia v Androide s krátkym prehľadom, čo práve uzavretý okruh robí Definujte profil, ktorý je dostupný offline. @@ -246,7 +247,7 @@ Wear Všetky dáta poslať znova Otvoriť nastavenia na hodinkách - Bazál: + Bazál Hodnota bazálu pod povoleným minimom. Profil nenastavený! Glykémia: Posledná glykémia: @@ -280,10 +281,10 @@ Profil Štandardná hodnota: 3 Toto je kľúčová hodnota zabezpečenia. Hovorí, že maximálny nastaviteľný bazál je trojnásobkom maximálneho denného bazálu. Spravidla to zrejme nebudete musieť meniť, prípadne si prečítate o téme \"3x max denný; 4x aktuálny\". Štandardná hodnota: 4 Toto je druhá kľúčová hodnota. Hovorí, že maximálna hodnota dočasného bazálu nikdy nebude väčšia, ako štvornásobok aktuálneho bazálu. Je to preto, aby se ľudia nedostali do nebezpečných hodnôt skôr, ako pochopia ako OpenAPS pracuje. Znovu, štandardná hodnota je 4 a väčšina ľudí ju nikdy nebude musieť meniť. Pokiaľ nestačí, obvykle je problém niekde inde. - Štandardná hodnota: 1.2\nToto je bezpečnostné nastavenie pre detekciu citlivosti (a čoskoro autotune). Hovorí, že autosens môže zvýšiť bazály, znížiť ISF a znížiť cieľovú hodnotu glykémie o 20%%. - Štandardná hodnota: 0.7\nToto je bezpečnostné nastavenie pre automatickú detekciu citlivosti. Hovorí, že automatická detekcia citlivosti môže znížiť bazály, zvýšiť ISF a zvýšiť cieľovú hodnotu glykémie na 70%. + Štandardná hodnota: 1.2\nToto je bezpečnostné nastavenie pre detekciu citlivosti (a čoskoro autotune). Hovorí, že autosens môže zvýšiť bazály, znížiť ISF (citlivosť na inzulín) a znížiť cieľovú hodnotu glykémie o 20%%. + Štandardná hodnota: 0.7\nToto je bezpečnostné nastavenie pre automatickú detekciu citlivosti. Hovorí, že automatická detekcia citlivosti môže znížiť bazály, zvýšiť ISF (citlivosť na inzulín) a zvýšiť cieľovú hodnotu glykémie na 70%. Autosense takisto upravuje cieľovú glykémiu - Štandardná hodnota: zapnuté\nToto nastavenie hovorí, že automatická detekcia citlivosti môže meniť tiež cieľové hodnoty glykémií. + Štandardná hodnota: zapnuté\nToto je používané, aby automatická detekcia citlivosti mohla okrem cieľovej hodnoty glekémie, upravovať aj citlivosť, prevody a bazály. Štandardná hodnota: 2\nToto nastavenie hovorí, po akú časť z hodnoty DIA uzavretý okruh po boluse čaká a nereaguje na zmeny glykémií (tu 3DIA/2 = 1,5h). Štandardná hodnota: 3.0 (AMA), alebo 8.0 (SMB) mg/dl/5min. Táto hodnota definuje minimálnu časť vstrebaných sacharidov za každých 5min. Táto hodnota ovplyvňuje výpočet COB. Pozor!\nZa normálnych okolností tieto hodnoty nemusíte meniť. Kliknete TU, PREČÍTAJTE si informácie a UISTITE sa, že im rozumiete skôr, ako ich začnete meniť. @@ -434,6 +435,7 @@ Povoliť vysielanie do iných aplikácií (napr. xDrip+). Nepovoľujte, pokiaľ máte nainštalovanú viac ako jednu AAPS, alebo NSClient inštanciu! Povoliť lokálne vysielanie. OpenAPS SMB + OpenAPS SMB s dynamickým ISF Povoliť UAM Povoliť SMB Použiť Super Mikro Bolusy namiesto dočasných bazálov, pre zrýchleniu účinku @@ -502,6 +504,7 @@ Iba záporné Výpočet COB Výpočet dočasného cieľa + Percentuálny výpočet Uzavretý okruh povolený APS vybrané NSClient má povolenie k zápisu @@ -757,8 +760,8 @@ Názov profilu obsahuje bodky.\nToto nie je podporované v NS.\nProfil nebude prenesený do NS. Spodná hodnota v oblasti cieľového rozsahu (iba zobrazovanie) Horná hodnota v oblasti cieľového rozsahu (iba zobrazovanie) - Vek: - Váha: + Vek + Váha ID: Odoslať Najčastejšie používaný profil: @@ -900,9 +903,74 @@ Chyby Spomaliť nahrávanie Stav dát glykémie + vek kanyly + vek náplasťovej pumpy + Náplasťová pumpa Použité prepočítané dáta Glykémia je príliš blízko:\n%1$s\n%2$s Identifikácia (E-mail, prezývka FB, alebo Discord atď.) Identifikácia nie je nastavená vo vývojárskom móde + dialog + aktuálna glykémia + správny výsledok v % + správny výsledok s jednotkami Nedostupný + vysoká + v rozsahu + nízka + rýchly pokles + klesajúca + pomaly klesajúca + stabilná + pomaly stúpajúca + stúpajúca + rýchlo stúpajúca + žiadny + neznámy + graf + kvalita glykémií + prepočítané + dvojité zápisy + inzulín + glykémia + zastaralé + nastaviť pripomienku + pridať nový profil + klonovať aktuálny profil + zmazať aktuálny profil + pridať nový do zoznamu + + Dočasný cieľ neznáma predvoľba: %1$s + Zrušenie bežiaceho dočasného cieľa? + Použité rozdielne jednotky v hodinkách a v telefóne! + Nulový dočasný cieľ - zrušenie bežiaceho dočasného cieľa? + Minimálna glykémia mimo rozsah! + Maximálna glykémia mimo rozsah! + Doč. cieľ:\nMin: %1$s\nMax: %2$s\nTrvanie: %3$s + Doč. cieľ:\nCieľ: %1$s\nTrvanie: %2$s + Doč. cieľ:\nDôvod: %1$s\nCieľ: %2$s\nTrvanie: %3$s + Rýchly bolus: %1$s\nInzulín: %2$.2fJI\nSacharidy: %3$dg + Kalkulačka: \nInzulín: %1$.2fJI\nSacharidy: %2$dg + Zobraziť záznam na zariadení: + Vybraný rýchly bolus už nie je k dispozícii, obnovte prosím dlaždicu + Žiadna aktuálna glykémia k základnému výpočtu! + Nie je nastavený žiadny aktívny profil! + Neznáme COB! Chýbajú glykémie, alebo bola práve reštartovaná aplikácia? + Sacharidy mimo povolený rozsah! + Kalk (IC: %2$.1f, ISF: %2$.1f) z:\" + Sacharidy: %1$.2fJI + COB: %1$.0fg %2$.2fJI + Gly: %1$.2fJI + Bazál IOB: %1$.2fJI + Bolus IOB: %1$.2fJI + Superbolus: %1$.2fJI + 15min trend: %1$.2fJI + Percentá: %1$.2fJI x %2$d%% ≈ %3$.2fJI + Inzulín mimo povolený rozsah!\nNie je možné podať %1$.2fJI + DC: %1$s + %1$s do %2$s + Pumpa nedostupná! + Neznámy príkaz k akcii: + Percentuálny podiel + Predvolené aplikáciou diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index 888cee6752..f657128eee 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -25,6 +25,7 @@ Synkroniserar dina data med Nightscout Så som algoritmen var definierad år 2017 Den senaste algoritmen för avancerade användare + Senaste algoritm för avancerade användare med dynamisk / automatisk ISF Visar loopens nuvarande tillstånd och knappar för de vanligaste funktionerna Visar en konstant avisering med en kort sammanfattning av vad din loop gör Definiera en profil som är tillgänglig offline. @@ -247,7 +248,7 @@ Eversense-appen. Klocka (Wear) Uppdatera klockans data Öppna inställningar på klockan - Basal: + Basaldos Basal understiger miniminivå. Profilen sattes inte. BG: Senaste BG: @@ -268,6 +269,7 @@ Eversense-appen. Konf Loop OAPS + DynISF LP Hem vPump @@ -435,6 +437,7 @@ Eversense-appen. Aktivera sändning till andra appar (som xDrip+) på denna telefon. Aktivera inte detta om du har fler än en förekomst av AAPS eller NSClient installerad! Aktivera lokala broadcasts OpenAPS SMB + OpenAPS SMB Dynamisk ISF Aktivera UAM Aktivera SMB Använd Super Micro Bolusar istället för temp basal för snabbare resultat @@ -503,6 +506,7 @@ Eversense-appen. Endast negativa Använd COB Använd temp målvärde + Procentuell beräkning Loop aktiverad APS vald NSClient kan uppdatera Nightscout @@ -758,8 +762,8 @@ Eversense-appen. Profilnamnet innehåller punkter.\nDetta stöds inte av NS.\nProfil överförs inte till NS. Nedre värdet för målområde (endast visning) Övre värdet för målområde (endast visning) - Ålder: - Vikt: + Ålder + Vikt ID: Spara Den vanligaste profilen: @@ -901,9 +905,74 @@ Eversense-appen. Fel Långsamma uppladdningar BG datastatus + kanylålder + slanglös pump ålder + Slanglös pump Omräknad data används BG för nära:\n%1$s\n%2$s Identifiering (e-post, FB, Discord-namn etc) Identifiering inte angiven i dev-läge + dialog + nuvarande BG + korrigera med % + korrigera med enheter Ej tillgängligt + hög + inom målområdet + låg + sjunker snabbt + sjunker + sjunker långsamt + stabilt + stiger långsamt + stiger + stiger snabbt + ingen + okänd + graf + Kvalitet på BG-data + omräknad + dubbla poster + insulin + blodglukos + föråldrad + ställ in påminnelse + lägg till ny profil + klona nuvarande profil + ta bort aktuell profil + lägg till ny i listan + + Tempmål okänd förinställning: %1$s + Avbryt temp-mål? + Olika enheter på klocka och telefon! + Noll-temp - avbyta nuvarande temp-mål? + Ogiltigt minimum BG! + Ogiltigt maximum BG! + Temp-mål:\nMin: %1$s\nMax: %2$s\nVaraktighet: %3$s + Temp-mål:\nMål: %1$s\nDuration: %2$s + Temp-mål:\Orsak: %1$s\nMål: %2$s\nVaraktighet: %3$s + Snabbsteg: %1$s\nInsulin: %2$.2fU\nKolhydrater: %3$dg + Kalkylator:\nInsulin: %1$.2fU\nKolhydrater: %2$dg + Visa post på enhet: + Vald kalkylator inte längre tillgänglig. Vänligen uppdatera din bricka + Inget nytt BG-värde att basera beräkning på! + Ingen aktiv profil vald! + Okänt COB! Saknas BG eller är appen nyss omstartad? + Max KH uppnått! + Kalkyl (IC: %2$.1f, ISF: %2$.1f) från:\" + Kolhydrater: %1$.2fU + COB: %1$.0fg %2$.2fU + BG: %1$.2fU + IOB från basal: %1$.2fU + IOB från bolus: %1$.2fU + Superbolus: %1$.2fU + 15\' trend: %1$.2fU + Procent: %1$.2fU x %2$d%% ≈ %3$.2fU + Max bolus uppnått!\nKan inte leverera %1$.2fU + TempM: %1$s + %1$s till %2$s + Ingen pump tillgänglig! + Okänt kommando: + Procent + Appens standardinställning diff --git a/app/src/main/res/values-tr-rTR/exam.xml b/app/src/main/res/values-tr-rTR/exam.xml index de2cbd5dff..750f43319d 100644 --- a/app/src/main/res/values-tr-rTR/exam.xml +++ b/app/src/main/res/values-tr-rTR/exam.xml @@ -171,7 +171,7 @@ https://androidaps.readthedocs.io/en/latest/EN/Usage/Profiles.html Profilinizde I:C oranı için birden fazla değer kullanabilirsiniz. Profilinizde ISF\'nizi değiştirirseniz, her zaman I:C oranınızı da değiştirmelisiniz. - İnsülin/Karbonhidrat Oranı (I:C oranı) + Karbonhidrat insülin Oranı (I:C oranı) Daha yüksek I:C oranları, belirli bir miktarda karbonhidrat için daha az insülin verilmesine yol açar. Daha düşük I:C oranları, belirli bir miktarda karbonhidrat için daha az insülin verilmesine yol açar. 0 COB\'niz varsa, IC oranını değiştirmek, belirli bir KŞ değerini düzeltmek için farklı insülin miktarına sebep olur. diff --git a/app/src/main/res/values-tr-rTR/strings.xml b/app/src/main/res/values-tr-rTR/strings.xml index b9ee7ff23a..1b1bba77e5 100644 --- a/app/src/main/res/values-tr-rTR/strings.xml +++ b/app/src/main/res/values-tr-rTR/strings.xml @@ -25,6 +25,7 @@ Nightscout ile verilerinizi senkronize eder 2017\'da algoritmanın durumu İleri düzey kullanıcılar için en yeni algoritma + Dinamik/otomatik İDF ile ileri düzey kullanıcılar için en yeni algoritma Döngünüzün mevcut durumunu ve en yaygın eylemler için düğmeleri görüntüler Döngü\'ün ne yaptığını kısa bir genel bakışla devam eden bir bildirimi gösterir Çevrimdışı kullanılabilen bir profil tanımlayın. @@ -246,7 +247,7 @@ Wear Tüm verileri yeniden gönderin Ayarları Wear\'da açın - Bazal oranı: + Bazal oranı Bazal değer minimumun altında. Profil ayarlanmadı! KŞ: Son KŞ: @@ -267,6 +268,7 @@ KONF DÖNGÜ OAPS + DYNISF YP GİRİŞ VPOMP @@ -435,6 +437,7 @@ Aktif Karbonhidratın ne kadar hızlı sindirildiğine ve KŞ\'nin beklenenden d Diğer uygulamalara (xDrip+ gibi) yayınları etkinleştirin. Yüklü birden fazla APPS veya NSClient örneğiniz varsa etkinleştirmeyin! Yerel yayınları etkinleştirin. OpenAPS SMB + OpenAPS SMB Dinamik İDF UAM etkinleştir SMB (Super Micro Bolus) etkinleştir Daha hızlı bir etki için geçici bazal yerine Super Micro Bolus kullanın @@ -472,7 +475,7 @@ Aktif Karbonhidratın ne kadar hızlı sindirildiğine ve KŞ\'nin beklenenden d Kaçırılan KŞ Okumaları Uyarılar ve bildirimler için sistem bildirimlerini kullan Uyarılar ve bildirimler için ses seviyesini kademeli olarak artırın - Yerel uyarıları + Yerel uyarılar KŞ bilgisi alınmadığında uyar Pompa ulaşılamıyorsa uyar Pompa ulaşılamaz eşiği [min] @@ -503,6 +506,7 @@ Aktif Karbonhidratın ne kadar hızlı sindirildiğine ve KŞ\'nin beklenenden d Sadece negatif COB (Aktif Karbonhidrat) hesaplaması Geçici hedef hesaplaması + Yüzde Hesaplaması Döngü etkin APS Seçildi NSClient\'in yazma izni var @@ -758,8 +762,8 @@ Aktif Karbonhidratın ne kadar hızlı sindirildiğine ve KŞ\'nin beklenenden d Profil adı noktalar içeriyor.\nBu NS tarafından desteklenmiyor.\n Profil NS\'a yüklenmez. Aralıktan daha düşük değer (sadece görüntüle) Aralıktan daha yüksek değer (Sadece görüntüle) - Yaş: - Kilo: + Yaş + Ağırlık Kimlik: Sunum En yaygın profil: @@ -901,9 +905,74 @@ Aktif Karbonhidratın ne kadar hızlı sindirildiğine ve KŞ\'nin beklenenden d Hatalar Yüklemeleri yavaşlat KŞ veri durumu + kanül yaşı + yama pompa yaşı + Yama pompa Kullanılan veriler yeniden hesaplandı KŞ çok yakın:\n%1$s\n%2$s Tanımlama (E-posta, FB veya Discord rumuz vs.) Tanımlama geliştirme modunda ayarlanmadı + diyalog + geçerli kan şekeri + % ile doğru sonuç + ünite ile doğru sonuç Mevcut değil + yüksek + aralık içinde + düşük + hızla düşüyor + düşüyor + yavaşça düşüyor + sabit + yavaşça yükseliyor + yükseliyor + hızla yükseliyor + yok + bilinmiyor + grafik + kan şekeri kalitesi + tekrar hesaplandı + çift giriş + insülin + kan şekeri + güncel değil + hatırlatıcıyı kur + yeni profil ekle + mevcut profili klonla + mevcut profil sil + listeye yeni ekle + + Geiçici hedef bilinmeyen ön ayarı: %1$s + Çalışan Geçici-Hedefler iptal edilsin mi? + Saatte ve telefonda farklı birimler kullanılıyor! + Sıfır-Geçici-Hedef - Çalışan Geçici-Hedefler iptal edilsin mi? + Min-KŞ aralık dışında! + Maks-KŞ aralık dışında! + Geçici Hedef:\nMin: %1$s\nMaks: %2$s\nSüre: %3$s + Geçici Hedef:\nHedef: %1$s\nSüre: %2$s + Geçici Hedef:\Neden: %1$s\nHedef: %2$s\nSüre: %3$s + Hızlı Asistan: %1$s\nİnsülin: %2$.2fU\nKarb: %3$dg + Hesap Mak.:\nİnsulin: %1$.2fÜ\nKarb: %2$dg + Girişi cihazda göster: + Seçili hızlı asistan artık mevcut değil, lütfen kutucuğu yenileyin + Hesaplamayı temel alacak yeni bir KŞ yok! + Etkin profil ayarlanmadı! + Aktif karbonhidrat bilinmiyor! KŞ okuması eksik veya son uygulama yeniden başlatılsın mı? + Karbonhidrat kısıtlaması ihlali! + Tarafından hesaplanan (IC: %2$.1f, İDF: %2$.1f):\" + Karb: %1$.2fÜ + COB: %1$.0fg %2$.2fÜ + KŞ: %1$.2fÜ + Bazal IOB: %1$.2fÜ + Bolus IOB: %1$.2fÜ + Süperbolus: %1$.2fÜ + 15\' trend: %1$.2fÜ + Yüzde: %1$.2fÜ x %2$d%% ≈ %3$.2fÜ + İnsülin kısıtlaması ihlali!\n%1$.2fÜ iletilemez + GeçiciH: %1$s + %1$s - %2$s + Pompa mevcut değil! + Bilinmeyen eylem komutu: + Yüzde + Uygulama varsayılanı diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index cabb02e0ad..e3f52dcdd0 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -180,7 +180,6 @@ 手表 重新发送所有数据 在手表上打开设置 - 基础率比值: 基础率值低于泵支持的最小值。配置文件没有设定 血糖: 上次血糖: @@ -562,4 +561,5 @@ 非常旧版本 2小时 + diff --git a/automation/src/main/res/values-cs-rCZ/strings.xml b/automation/src/main/res/values-cs-rCZ/strings.xml index 85aac82cba..1f30aba334 100644 --- a/automation/src/main/res/values-cs-rCZ/strings.xml +++ b/automation/src/main/res/values-cs-rCZ/strings.xml @@ -81,6 +81,7 @@ WiFi SSID %1$s %2$s Autosens %1$s %2$s %% Autosens % + Automatická detekce senzitivity %3$s %1$s %2$s Rozdíl glykémie Rozdíl glykémie [%1$s] diff --git a/automation/src/main/res/values-de-rDE/strings.xml b/automation/src/main/res/values-de-rDE/strings.xml index 9d02bae0e6..3cb46b8eaa 100644 --- a/automation/src/main/res/values-de-rDE/strings.xml +++ b/automation/src/main/res/values-de-rDE/strings.xml @@ -81,6 +81,7 @@ WiFi SSID %1$s %2$s Autosens %1$s %2$s %% Autosens % + Auto sens %3$s %1$s %2$s BZ-Unterschied BZ-Unterschied [%1$s] diff --git a/automation/src/main/res/values-es-rES/strings.xml b/automation/src/main/res/values-es-rES/strings.xml index f4a76072f7..e9d20402e6 100644 --- a/automation/src/main/res/values-es-rES/strings.xml +++ b/automation/src/main/res/values-es-rES/strings.xml @@ -81,6 +81,7 @@ SSID WiFi %1$s %2$s Autosens %1$s %2$s %% Autosens % + Auto sens %3$s %1$s %2$s Diferencia de glucosa Diferencia de glucosa %1$s diff --git a/automation/src/main/res/values-fr-rFR/strings.xml b/automation/src/main/res/values-fr-rFR/strings.xml index f1ce0abe0d..9e5a3874bd 100644 --- a/automation/src/main/res/values-fr-rFR/strings.xml +++ b/automation/src/main/res/values-fr-rFR/strings.xml @@ -81,6 +81,7 @@ SSID WiFi %1$s %2$s Autosens %1$s %2$s %% Autosens % + Auto sens %3$s %1$s %2$s Delta de glycémies Delta Glyc. [%1$s] diff --git a/automation/src/main/res/values-iw-rIL/strings.xml b/automation/src/main/res/values-iw-rIL/strings.xml index 5ba51cb7fa..b166bd5e0a 100644 --- a/automation/src/main/res/values-iw-rIL/strings.xml +++ b/automation/src/main/res/values-iw-rIL/strings.xml @@ -81,6 +81,7 @@ WiFi SSID %1$s %2$s Autosens %1$s %2$s %% Autosens % + חישוב רגישות אוטומטי (Autosens) %3$s %1$s %2$s הפרש רמת סוכר הפרש רמת סוכר [%1$s] diff --git a/automation/src/main/res/values-nl-rNL/strings.xml b/automation/src/main/res/values-nl-rNL/strings.xml index b32d9b9f19..e686d38c7b 100644 --- a/automation/src/main/res/values-nl-rNL/strings.xml +++ b/automation/src/main/res/values-nl-rNL/strings.xml @@ -81,6 +81,7 @@ WiFi SSID %1$s %2$s Gevoeligheid %1$s %2$s %% Gevoeligheid % + Autosens %3$s %1$s %2$s BG verschil BG verschil [%1$s] diff --git a/automation/src/main/res/values-no-rNO/strings.xml b/automation/src/main/res/values-no-rNO/strings.xml index 9ddd8db943..f3d1e75f8b 100644 --- a/automation/src/main/res/values-no-rNO/strings.xml +++ b/automation/src/main/res/values-no-rNO/strings.xml @@ -81,6 +81,7 @@ WiFi SSID %1$s %2$s Autosens %1$s %2$s %% Autosens % + Autosens %3$s %1$s %2$s BS forskjell BS forskjell [%1$s] diff --git a/automation/src/main/res/values-ru-rRU/strings.xml b/automation/src/main/res/values-ru-rRU/strings.xml index 96a71d6cd0..a1d0b8c967 100644 --- a/automation/src/main/res/values-ru-rRU/strings.xml +++ b/automation/src/main/res/values-ru-rRU/strings.xml @@ -81,6 +81,7 @@ WiFi SSID %1$s %2$s Автосенс %1$s %2$s %% Автосенс % + Auto sens %3$s%1$s%2$s Разница Гк Разница ГК [%1$s] diff --git a/automation/src/main/res/values-sk-rSK/strings.xml b/automation/src/main/res/values-sk-rSK/strings.xml index 4e39609a62..d44107e9d7 100644 --- a/automation/src/main/res/values-sk-rSK/strings.xml +++ b/automation/src/main/res/values-sk-rSK/strings.xml @@ -81,6 +81,7 @@ WiFi SSID %1$s %2$s Autosens %1$s %2$s %% Autosens % + Automatická detekcia citlivosti %3$s %1$s %2$s Rozdiel glykémie Rozdiel glykémie [%1$s] diff --git a/automation/src/main/res/values-sv-rSE/strings.xml b/automation/src/main/res/values-sv-rSE/strings.xml index 98c412a7db..aa9770c273 100644 --- a/automation/src/main/res/values-sv-rSE/strings.xml +++ b/automation/src/main/res/values-sv-rSE/strings.xml @@ -81,6 +81,7 @@ WiFi SSID %1$s %2$s Autosens %1$s %2$s %% Autosens % + Auto sens %3$s %1$s %2$s BG-förändring BG-förändring [%1$s] diff --git a/automation/src/main/res/values-tr-rTR/strings.xml b/automation/src/main/res/values-tr-rTR/strings.xml index cc4baeade2..87ddc50210 100644 --- a/automation/src/main/res/values-tr-rTR/strings.xml +++ b/automation/src/main/res/values-tr-rTR/strings.xml @@ -81,6 +81,7 @@ WiFi SSID %1$s %2$s Otoduyarlılık %1$s %2$s %% Otoduyarlılık % + Oto duyarlılık %3$s %1$s %2$s KŞ farkı KŞ farkı [%1$s] diff --git a/combo/src/main/res/values-cs-rCZ/strings.xml b/combo/src/main/res/values-cs-rCZ/strings.xml index 8f3682d2a8..5301ba10a3 100644 --- a/combo/src/main/res/values-cs-rCZ/strings.xml +++ b/combo/src/main/res/values-cs-rCZ/strings.xml @@ -51,4 +51,10 @@ Počet dočasných bazálů Bolus zastaven Zastavování bolusu + Počet chyb komun. + Zobr. počet chyb komun. + Zobrazí počet chyb při komunikaci s Ruffy. Číslo vyšší než 0 obvykle značí problémy s Ruffy (může být nutné restartovat). + Nikdy + Když dojde k chybě + Vždy diff --git a/combo/src/main/res/values-es-rES/strings.xml b/combo/src/main/res/values-es-rES/strings.xml index 70255b9e5d..e72e4ebed8 100644 --- a/combo/src/main/res/values-es-rES/strings.xml +++ b/combo/src/main/res/values-es-rES/strings.xml @@ -51,4 +51,10 @@ Contador TBR Bolo interrumpido Deteniendo bolo + Comm. Error contador + Mostrar contador de errores comm + Muestra el recuento de errores, cuando se comunica con Ruffy. En la mayoría de los casos un número mayor que 0 indica problemas de comunicación con Ruffy (puede que sea necesario reiniciar). + Nunca + Cuando Error + Siempre diff --git a/combo/src/main/res/values-no-rNO/strings.xml b/combo/src/main/res/values-no-rNO/strings.xml index a85fb7cd4e..d4e77f09b0 100644 --- a/combo/src/main/res/values-no-rNO/strings.xml +++ b/combo/src/main/res/values-no-rNO/strings.xml @@ -51,4 +51,10 @@ Antall temp basaler Bolus stoppet Stopper bolus + Komm. Feiltelling + Vis komm. feiltelling + Viser antall feil i kommunikasjonen med Ruffy. Hvis høyere tall enn 0 vises innebærer det problemer med Ruffy kommunikasjonen og en omstart kan være nødvendig. + Aldri + Ved feil + Alltid diff --git a/combo/src/main/res/values-ru-rRU/strings.xml b/combo/src/main/res/values-ru-rRU/strings.xml index a51d6b9e7c..3b397051e1 100644 --- a/combo/src/main/res/values-ru-rRU/strings.xml +++ b/combo/src/main/res/values-ru-rRU/strings.xml @@ -51,4 +51,10 @@ Отсчет временного базала TBR Болюс остановлен Остановка болюса + Ошибок связи + Показать количество ошибок связи + Показывает количество ошибок связи с Ruffy. В большинстве случаев число выше 0 означает проблемы коммуникации с Ruffy (может потребоваться перезапуск). + Никогда + При ошибке + Всегда diff --git a/combo/src/main/res/values-sv-rSE/strings.xml b/combo/src/main/res/values-sv-rSE/strings.xml index 6019e91527..e54d0a93ee 100644 --- a/combo/src/main/res/values-sv-rSE/strings.xml +++ b/combo/src/main/res/values-sv-rSE/strings.xml @@ -51,4 +51,10 @@ Antal temp basaler Bolus avbruten Avbryter bolus + Antal komm-fel + Visa antal komm-fel + Visar antal fel när du kommunicerar med Ruffy. I de flesta fall indikerar en siffra högre än 0 att Ruffy har kommunikationsproblem (omstart kan behövas). + Aldrig + Vid fel + Alltid diff --git a/combo/src/main/res/values-tr-rTR/strings.xml b/combo/src/main/res/values-tr-rTR/strings.xml index 932672a88d..889c8e4a69 100644 --- a/combo/src/main/res/values-tr-rTR/strings.xml +++ b/combo/src/main/res/values-tr-rTR/strings.xml @@ -51,4 +51,10 @@ TBR (GBO) Geçici Bazal Oranı sayısı Bolus durdu Bolus durdurma + İletişim Hata sayısı + İletişim hata sayısını göster + Ruffy ile iletişim kurarken hata sayısını gösterir. Genelde 0\'dan büyük sayılar, Ruffy iletişim sorunlarını belirtir (yeniden başlatma gerekebilir). + Asla + Hata Olduğunda + Her zaman diff --git a/core/src/main/res/values-cs-rCZ/strings.xml b/core/src/main/res/values-cs-rCZ/strings.xml index ea19cef4d5..25c899fe6c 100644 --- a/core/src/main/res/values-cs-rCZ/strings.xml +++ b/core/src/main/res/values-cs-rCZ/strings.xml @@ -48,6 +48,11 @@ Citlivost Bazál Cíl + Doba působnosti inzulínu + Inzulíno-sacharidový poměr + Citlivost na inzulín + Bazál + Cílová glykémie Inicializuji ... Sériové číslo Baterie @@ -105,6 +110,7 @@ Poznámky Odstranit Přidat nový + Přidat novou nad Data přicházejí z jiné pumpy. Změňte ovladač pro obnovení stavu pumpy. Max bazál omezen na %1$.2f U/h: %2$s @@ -127,6 +133,7 @@ Pro vyhledání Bluetooth zařízení na novějších telefonech musí být povoleno zjišťování polohy. AAPS vás nesleduje a po provedení párování můžete tuto volbu opět zakázat. před %1$d min + před %1$d minutamí před %1$.1f h h dnů @@ -440,6 +447,8 @@ Bolus OK Pumpa spárována Insight Tlačítko Obnovit + snížení %1$s o %2$s + zvýšení %1$s o %2$s %1$d den %1$d dnů diff --git a/core/src/main/res/values-da-rDK/strings.xml b/core/src/main/res/values-da-rDK/strings.xml index 7a6d0f8c0f..ec20dfa6d7 100644 --- a/core/src/main/res/values-da-rDK/strings.xml +++ b/core/src/main/res/values-da-rDK/strings.xml @@ -48,6 +48,11 @@ ISF Basal Målværdi + Varighed af insulin aktivitet + Insulin til kulhydrat forhold + Insulinfølsomhedsfaktor + Basal rate + Blodsukker mål Initialiserer ... Serienummer Batteri diff --git a/core/src/main/res/values-de-rDE/strings.xml b/core/src/main/res/values-de-rDE/strings.xml index 88b085ad88..0c062833a0 100644 --- a/core/src/main/res/values-de-rDE/strings.xml +++ b/core/src/main/res/values-de-rDE/strings.xml @@ -48,6 +48,11 @@ ISF Basal Ziel + Insulinwirkdauer (duration of insulin action) + Insulin-zu-KH-Faktor + ISF: Insulin Sensitivitäts-Faktor (\"Korrektur-Faktor\") + Basalrate + BZ Ziel Initialisierung... Seriennummer Batterie @@ -105,6 +110,7 @@ Notizen Löschen Weiteren hinzufügen + Neu oben hinzufügen Daten kommen von einer anderen Pumpe. Wechsle den Pumpentreiber. Begrenzung der max. Basalrate auf %1$.2f IE/h wegen %2$s @@ -127,6 +133,7 @@ Auf neueren Geräten muss für die Bluetooth-Erkennung der Standortdienst aktiviert sein. AAPS speichert keine Standortdaten und der Dienst kann nach erfolgreichem Pairing wieder deaktiviert werden. vor %1$d Min. + vor %1$d Minuten vor %1$.1f Stunde h Tage @@ -440,6 +447,8 @@ Bolus OK Pumpe gekoppelt Insight Refresh Button + abnehmend %1$s mit %2$s + zunehmend %1$s mit %2$s %1$d Tag %1$d Tage diff --git a/core/src/main/res/values-es-rES/strings.xml b/core/src/main/res/values-es-rES/strings.xml index 0b6e9dfa98..103685ff60 100644 --- a/core/src/main/res/values-es-rES/strings.xml +++ b/core/src/main/res/values-es-rES/strings.xml @@ -48,6 +48,11 @@ ISF (Factor Sensibilidad Insulina) Dosis Basal Objetivo + Duración de la acción de la insulina + Ratio de insulina/carbohidratos + Factor de sensibilidad a la insulina + Tasa Basal + Objetivo de glucosa en sangre Iniciando... Número de serie Batería @@ -105,6 +110,7 @@ Notas Eliminar Añadir nuevo + Añadir nuevo arriba Los datos proceden de una bomba diferente. Cambia el controlador de la bomba para resetear su estado. Limitando max basal rate a %1$.2f U/h debido a %2$s @@ -127,6 +133,7 @@ Para activar la visibilidad Bluetooth en nuevos dispositivos, la ubicación debe estar habilitada. AAPS no hace un seguimiento de su ubicación y se puede desactivar después de realizar la vinculación. hace %1$d m + Hace %1$d minutos hace %1$.1f h h días @@ -440,6 +447,8 @@ Bolo OK Bomba emparejada Botón de refresco de Insight + decrecimiento %1$s por %2$s + incremento %1$s por %2$s %1$d día %1$d días diff --git a/core/src/main/res/values-fr-rFR/strings.xml b/core/src/main/res/values-fr-rFR/strings.xml index 2c9b1894ee..ed61273bf4 100644 --- a/core/src/main/res/values-fr-rFR/strings.xml +++ b/core/src/main/res/values-fr-rFR/strings.xml @@ -48,6 +48,11 @@ SI Basal Cible + Durée d\'Action de l\'Insuline + Rapport Glucides / Insuline + Facteur de sensibilité à l\'insuline (SI) + Débit de Basal + Glycémie cible En cours d\'initialisation... Numéro de série Niveau batterie @@ -105,6 +110,7 @@ Notes Supprimer Ajouter + Ajouter le nouveau au-dessus Les données proviennent de différentes pompes. Changer le pilote de la pompe pour réinitialiser l\'état de la pompe. Limiter le débit de basal max à %1$.2f U/h à cause de %2$s @@ -127,6 +133,7 @@ La localisation doit être activée sur les nouveaux appareils pour que la recherche Bluetooth fonctionne. AAPS n\'enregistre pas votre localisation et la localisation peut être désactivée après l\'appairage. il y a %1$d m + Il y a %1$d minutes il y a %1$.1f h h jours @@ -440,6 +447,8 @@ Bolus OK Pompe appairée Actualisation état Insight + réduire %1$s par %2$s + incrémenter %1$s par %2$s %1$d jour %1$d jours diff --git a/core/src/main/res/values-iw-rIL/strings.xml b/core/src/main/res/values-iw-rIL/strings.xml index ebe5c770d4..6c9b0aa6fc 100644 --- a/core/src/main/res/values-iw-rIL/strings.xml +++ b/core/src/main/res/values-iw-rIL/strings.xml @@ -48,6 +48,11 @@ ISF אינסולין בזאלי ערך מטרה + משך פעילות האינסולין + יחס אינסולין-פחמימות + יחס התיקון (ISF) + מינון בזאלי + ערך מטרה מאתחל... מספר סידורי סוללה @@ -105,6 +110,7 @@ הערות הסרה הוסף חדש + הוסף חדש למעלה הנתונים מגיעים ממשאבה אחרת. בחרו מחדש את סוג המשאבה כדי לאפס את מצב המשאבה. מגביל את הקצב הבזאלי המרבי ל-%1$.2f יח\' לשעה בגלל %2$s @@ -127,6 +133,7 @@ בכדי שסריקת בלוטות\' תעבוד יש לאפשר את שירות המיקום. AAPS לא עוקב אחר המיקום שלכם וניתן להפסיק את השירות לאחר סיום הצימוד. לפני %1$d דקות + לפני %1$d דקות לפני %1$.1f שעות ש\' ימים diff --git a/core/src/main/res/values-nl-rNL/strings.xml b/core/src/main/res/values-nl-rNL/strings.xml index b72ebb97b4..230a54471a 100644 --- a/core/src/main/res/values-nl-rNL/strings.xml +++ b/core/src/main/res/values-nl-rNL/strings.xml @@ -48,6 +48,11 @@ ISF Basaal Streefdoel + Duur van insuline activiteit + Insuline - Koolhydraat ratio + Insuline gevoeligheidsfactor + Basaalstand + Bloedglucose doelwaarde Initialiseren... Serie nummer Batterij @@ -105,6 +110,7 @@ Notities Verwijder Voeg nieuw toe + Voeg nieuw hierboven toe Data komt van een andere pomp. Wijzig de pomp driver om de pomp status te resetten. Beperken van basaal tot max %1$.2f E/uur wegens de %2$s @@ -127,6 +133,7 @@ Om Bluetooth discovery met nieuwere apparaten te laten werken moet locatie worden ingeschakeld. AAPS volgt je locatie niet en locatie kan ook weer worden uitgeschakeld nadat het koppelen is gelukt. %1$d m geleden + %1$d minuten geleden %1$.1f u geleden u dagen @@ -440,6 +447,8 @@ Bolus OK Pomp gekoppeld Insight actualiseren knop + verlaag %1$s met %2$s + verhoog %1$s met %2$s %1$d dag %1$d dagen diff --git a/core/src/main/res/values-no-rNO/strings.xml b/core/src/main/res/values-no-rNO/strings.xml index 6bb5c7bce0..ad3cd294e6 100644 --- a/core/src/main/res/values-no-rNO/strings.xml +++ b/core/src/main/res/values-no-rNO/strings.xml @@ -48,6 +48,11 @@ ISF Basal Målverdi + Insulinets virkningstid (DIA) + Insulin- til karbohydratfaktor + Insulin sensitivitetsfaktor (ISF) + Basal rate + Blodsukkermål Starter opp... Serienummer Batteri @@ -105,6 +110,7 @@ Merknader Fjern Legg til ny + Legg til ny over Data kommer fra forskjellige pumper. Bytt pumpevalg for å nullstille pumpens tilstand. Begrenser maks basal dose til %1$.2f E/t på grunn av %2$s @@ -127,6 +133,7 @@ Bluetooth søk på nye mobiler virker bare når posisjonstjeneste er aktivert. AAPS lagrer ikke dine posisjonsdata og den kan derfor slås av etter vellykket sammenkobling. %1$d min siden + %1$d minutter siden %1$.1f timer siden t dager @@ -440,6 +447,8 @@ Bolus OK Pumpe sammenkoblet Insight oppdateringsknapp + reduser %1$s med %2$s + øk %1$s med %2$s %1$d dag %1$d dager diff --git a/core/src/main/res/values-ru-rRU/strings.xml b/core/src/main/res/values-ru-rRU/strings.xml index c21941b0ce..0d36727b0e 100644 --- a/core/src/main/res/values-ru-rRU/strings.xml +++ b/core/src/main/res/values-ru-rRU/strings.xml @@ -48,6 +48,11 @@ ISF (чувствительность к инсулину) базал Целевое значение СК: + Продолжительность действия инсулина + Соотношение инсулин/углеводы I: C + Фактор Чувствительности к Инсулину (ISF) + Скорость базала + Целевая ГК инициализация... Серийный номер батарея @@ -105,6 +110,7 @@ Заметки Удалить Добавить новый + Добавить строку сверху Данные поступают с другой помпы. Измените драйвер помпы, чтобы сбросить ее состояние. Макс базальный уровень ограничен до %1$.2f ед/ч вследствие %2$s @@ -127,6 +133,7 @@ Для обнаружения Bluetooth на новых устройствах необходимо включить геолокацию. AAPS не отслеживает ваше местоположение и может быть отключен после успешного сопряжения. %1$d мин. назад + %1$d минут назад %1$.1fч. назад ч дн @@ -440,6 +447,8 @@ болюс ОК Помпа сопряжена Кнопка \"Обновить Insight\" + снижение %1$s на %2$s + увеличение %1$s на %2$s %1$d день %1$d дня diff --git a/core/src/main/res/values-sk-rSK/strings.xml b/core/src/main/res/values-sk-rSK/strings.xml index 26b740444f..9dd3823963 100644 --- a/core/src/main/res/values-sk-rSK/strings.xml +++ b/core/src/main/res/values-sk-rSK/strings.xml @@ -48,6 +48,11 @@ Citlivosť Bazál Cieľ + Doba pôsobenia inzulínu + Inzulíno-sacharidový pomer + Citlivosť na inzulín + Bazál + Cieľová glykémia Inicializácia ... Sériové číslo Batéria @@ -105,6 +110,7 @@ Poznámky Vymazať Pridať nový + Pridať novú nad Dáta prichádzajú z inej pumpy. Zmeňte ovládač pre obnovenie stavu pumpy. Max bazál obmedzený na %1$.2f JI/h: %2$s @@ -127,6 +133,7 @@ Pre vyhľadanie Bluetooth zariadení na novších telefónoch musí byť povolené zisťovanie polohy. AAPS vás nesleduje a po úspešnom spárovaní môžete túto voľbu opäť zakázať. pred %1$d min + pred %1$d minútami pred %1$.1f h h dní @@ -440,6 +447,8 @@ Bolus OK Pumpa spárovaná Insight Tlačítko Obnoviť + zníženie %1$s o %2$s + zvýšenie %1$s o %2$s %1$d deň %1$d dní diff --git a/core/src/main/res/values-sv-rSE/strings.xml b/core/src/main/res/values-sv-rSE/strings.xml index 0b4d5a1649..1ae6ff61b9 100644 --- a/core/src/main/res/values-sv-rSE/strings.xml +++ b/core/src/main/res/values-sv-rSE/strings.xml @@ -48,6 +48,11 @@ ISF Basal Målvärde + Insulinets verkningstid + Insulin till kolhydratförhållande + Insulinkänslighetsfaktor + Basaldos + Mål-BG Startar... Serienummer Batterinivå @@ -105,6 +110,7 @@ Anteckning Ta bort Lägg till + Lägg till nytt ovan Data kommer från en annan pump. Byt pumpdrivrutin för att återställa. Max basal: %1$.2f E/h pga %2$s @@ -127,6 +133,7 @@ För att Bluetooth ska fungera med nyare enheter, måste platsdata vara aktiverat. AAPS sparar inte din plats och det kan stängas av efter att enheten har parkopplats. %1$dm sedan + %1$d minuter sedan %1$.1f tim sedan h dagar @@ -440,6 +447,8 @@ Bolus OK Pump parkopplad Uppdat. knapp för Insight + minska %1$s med %2$s + öka %1$s med %2$s %1$d dag %1$d dagar diff --git a/core/src/main/res/values-tr-rTR/strings.xml b/core/src/main/res/values-tr-rTR/strings.xml index 8b1cc7f890..90e1823414 100644 --- a/core/src/main/res/values-tr-rTR/strings.xml +++ b/core/src/main/res/values-tr-rTR/strings.xml @@ -48,6 +48,11 @@ İDF Bazal Hedef + İnsülin Etki Süresi + Karbonhidrat insülin Oranı (I:C oranı) + İnsülin Duyarlılık Faktörü + Bazal oranı + Kan Şekeri Hedefi Başlatılıyor ... Seri numarası Pil @@ -105,6 +110,7 @@ Notlar Kaldır Yeni ekle + Yukarı yeni ekle Veriler farklı pompadan geliyor. Pompa durumunu sıfırlamak için pompa sürücüsünü değiştirin. %2$s nedeniyle max bazal oranı %1$.2f Ü/s ile sınırlı @@ -127,6 +133,7 @@ Bluetooth cihaz bulmanın daha yeni cihazlarda çalışması için konum etkinleştirilmelidir. AAPS konumunuzu izlemez ve eşleştirme başarılı olduktan sonra devre dışı bırakılabilir. %1$d dak önce + %1$d dakika önce %1$.1f s önce s gün @@ -440,6 +447,8 @@ Bolus OK Pompa eşleştirildi Insight Yenileme Düğmesi + %2$s\'dan %1$s\'a azalma + %2$s\'dan %1$s\'a artış %1$d gün %1$d gün diff --git a/medtronic/src/main/res/values-tr-rTR/strings.xml b/medtronic/src/main/res/values-tr-rTR/strings.xml index 719df91378..f5977cd52f 100644 --- a/medtronic/src/main/res/values-tr-rTR/strings.xml +++ b/medtronic/src/main/res/values-tr-rTR/strings.xml @@ -7,7 +7,6 @@ Pompa Tipi Pompa Frekansı Bolus göndermeden önceki bekleme süresi (sn) - Pompadaki Maks Bolus (U) Pompadaki Maks Bazal (Ü/s) Medtronic Kodlama ABD & Kanada (916 MHz) diff --git a/omnipod-common/src/main/res/values-da-rDK/strings.xml b/omnipod-common/src/main/res/values-da-rDK/strings.xml index aeba6eca11..b75bc2acc6 100644 --- a/omnipod-common/src/main/res/values-da-rDK/strings.xml +++ b/omnipod-common/src/main/res/values-da-rDK/strings.xml @@ -62,7 +62,7 @@ Aktive pod alarmer Firmwareversion Tid på Pod - %1$.2fIE/t @%2$s (%3$d/%4$d minutter) + %1$.2fE/t @%2$s (%3$d/%4$d minutter) %1$.2f IE tilbage Over 50 IE tilbage Fejl diff --git a/omnipod-dash/src/main/res/values-nl-rNL/strings.xml b/omnipod-dash/src/main/res/values-nl-rNL/strings.xml index a4029e02f0..ab89814c50 100644 --- a/omnipod-dash/src/main/res/values-nl-rNL/strings.xml +++ b/omnipod-dash/src/main/res/values-nl-rNL/strings.xml @@ -36,4 +36,6 @@ %1$.2f eh worden toegediend Insuline levering is opgeschort Verbinding met pod verbroken + Een andere bolus wordt op dit moment toegediend + Niet voldoende insuline in het reservoir diff --git a/omnipod-eros/src/main/res/values-iw-rIL/strings.xml b/omnipod-eros/src/main/res/values-iw-rIL/strings.xml index 3f2d2beed7..650281daee 100644 --- a/omnipod-eros/src/main/res/values-iw-rIL/strings.xml +++ b/omnipod-eros/src/main/res/values-iw-rIL/strings.xml @@ -67,7 +67,7 @@ יומן פעימות (מועתק ללוח ההעתקה) מלאו פוד חדש עם מספיק אינסולין לשלושה ימים.\n\nהקשיבו לשני צפצופים מהפוד במהלך המילוי. הם מציינים שהכמות המינימלית של 80 יחידות הוכנסה. הקפידו לרוקן לחלוטין את מזרק המילוי, גם לאחר שמיעת שני הצפצופים.\n\nלאחר מילוי הפוד, יש ללחוץ הבא.\n\nהערה: נא לא להסיר עדיין את מכסה המחט.\n הערה: נא להניח את הריילילינק במצב עומד ובמרחק סנטימטרים בודדים מהפוד. - מנסה לצמד את הפוד החדש ולאתחלו.\n\nכאשר תהליך האתחול יושלם, ניתן ללחוץ על הבא.\n\nשימו לב: נא למקם את הריילילנק במצב אנכי ולמקם את הפוד כמה סנטימטרים ממנו. + מנסה לצמד את הפוד החדש ולאתחלו.\n\nכאשר תהליך האתחול יושלם, ניתן ללחוץ על הבא.\n\nשימו לב: נא למקם את הריילילינק במצב אנכי ולמקם את הפוד מספר סנטימטרים ממנו. לא בטוח diff --git a/wear/src/main/res/values-bg-rBG/strings.xml b/wear/src/main/res/values-bg-rBG/strings.xml index 5b9a48ce59..5343d8b32c 100644 --- a/wear/src/main/res/values-bg-rBG/strings.xml +++ b/wear/src/main/res/values-bg-rBG/strings.xml @@ -54,19 +54,15 @@ История Олекотена история Анимации - Калкулатор в менюто Пълнене в менюто Единична цел - Калкулатор с % Допълнителни действия при почукване Unicode кодиране Версия: Настройки на Watchface Погледнете в конфигурацията, моля. Врем цел - Калкулатор Болус - уд. въгл. Настройки Статус Ре-синхр. @@ -74,22 +70,12 @@ Без Стандартен Меню - продължителност - цел - ниско - висока - вълехидрати - % от профила - старт [min] - прод [h] - инсулин Шаблон 1 Шаблон 2 Шаблон 3 Неограничено кол ПОТВЪРДИ отместване - болус Болус прогрес натиснете за отмяна СПРИ БОЛУС diff --git a/wear/src/main/res/values-cs-rCZ/strings.xml b/wear/src/main/res/values-cs-rCZ/strings.xml index 197d545f72..ce07b6ca5a 100644 --- a/wear/src/main/res/values-cs-rCZ/strings.xml +++ b/wear/src/main/res/values-cs-rCZ/strings.xml @@ -11,6 +11,9 @@ AAPS (Cockpit) AAPS (Steampunk) AAPS (DigitalStyle) + AAPS(Akce) + AAPS(Doč. cíl) + AAPS(Rychlý bolus) Žádná data! Stará data! Od %1$s @@ -54,10 +57,10 @@ Kroužek Historie Světlý kroužek Historie Animace - Kalkulačka v nabídce + Kalkulačka v menu Plnění v nabídce Jeden cíl - Procenta z kalkulátoru + Procento kalkulačky Akce po klepnutí na komplikaci Znaky Unicode v komplikacích Verze: @@ -65,8 +68,11 @@ Podívejte se na konfiguraci hodinek prosím. TempT Kalkulačka + Kalk + Ošetření + Ošetř Bolus - eCarbs + Sach Nastavení Stav Re-Sync @@ -74,22 +80,31 @@ Nic Výchozí Menu - trvání - cíl - nízká - vysoká - sacharidy - procento - začátek [min] - trvání [h] - inzulín + XL + Trvání + Požadován dočasný cíl + Požadován rychlý bolus + Požadováno ošetření + Požadován bolus + Požadován kalkulátor + Požadováno plnění + Požadovány sacharidy + Požadován profil + Cíl + Nízký + Vysoký + Sacharidy + Procento + Začátek [min] + Trvání [h] + Inzulín Předvolba 1 Předvolba 2 Předvolba 3 Libovolné množství POTVRDIT posun času - bolus + Bolus Průběh vydávání bolusu stisknutím tlačítka akci zrušíte ZRUŠIT BOLUS @@ -142,4 +157,13 @@ Při nabíjení Vždy zapnuto Vždy zapnuto a nabíjení + Jídlo + Hypo + Aktivita + Ručně + Zrušit + Žádný + Není dostupná žádná konfigurace + Ovládání hodinkami vypnuto + Žádná data k dispozici diff --git a/wear/src/main/res/values-da-rDK/strings.xml b/wear/src/main/res/values-da-rDK/strings.xml index 3dcd7061e7..048c025c20 100644 --- a/wear/src/main/res/values-da-rDK/strings.xml +++ b/wear/src/main/res/values-da-rDK/strings.xml @@ -54,19 +54,15 @@ Ring Historik Lys Ring Historik Animationer - Bolus Guide i menu Prime i menuen Enkelt Mål - Guide Procentdel Complication handling ved tryk Unicode i komplikationer Version: flere Watchface indstillinger Se venligst på Watchface-konfigurationen. MidlertidigMål - Guide Bolus - eCarb Indstillinger Status Gensynkronisering @@ -74,22 +70,12 @@ Ingen Standard Menu - varighed - mål - lav - høj - kulhydrater - procent - start [min] - varighed [h] - insulin Forvalg 1 Forvalg 2 Forvalg 3 Fri mængde BEKRÆFT tidsforskydning - bolus Bolus Fremskridt tryk for at annullere ANNULLER BOLUS diff --git a/wear/src/main/res/values-de-rDE/strings.xml b/wear/src/main/res/values-de-rDE/strings.xml index 4f8b972840..577597b0cc 100644 --- a/wear/src/main/res/values-de-rDE/strings.xml +++ b/wear/src/main/res/values-de-rDE/strings.xml @@ -54,19 +54,15 @@ Ring BZ-Historie Ring BZ-Historie light Animationen - Rechner im Menü Befüllung im Menü Einzelzielwert - Rechner mit % Tipp Komplikation Unicode in Komplikationen Version: weitere Watchface Einstellungen Schaue Dir bitte die Watchface-Konfiguration an. Temp. Ziel - Rechner Bolus - eCarb Einstellung Status Erneut synchronisieren @@ -74,22 +70,12 @@ Kein(e) Standard Menü - Dauer - Ziel - niedrig - hoch - gKH - %-Satz - Start [min] - Dauer [h] - Insulin Voreinstellung 1 Voreinstellung 2 Voreinstellung 3 Freie Menge BESTÄTIGEN Zeitverschiebung - Bolus Bolusabgabe läuft Zum Abbrechen drücken Bolus löschen diff --git a/wear/src/main/res/values-es-rES/strings.xml b/wear/src/main/res/values-es-rES/strings.xml index d065e87a79..2ac83ae52c 100644 --- a/wear/src/main/res/values-es-rES/strings.xml +++ b/wear/src/main/res/values-es-rES/strings.xml @@ -11,6 +11,9 @@ AAPS (Cockpit) AAPS (Steampunk) AAPS (Digital) + AAPS(Acciones) + AAPS(Objetivo Temporal) + AAPS(Asistente Rápido) Sin datos Datos antiguos Desde %1$s @@ -54,19 +57,22 @@ Historial del aro Historial de aro ligero Animaciones - Asistente en el menú + Calculadora en el menú Cebar en menú Objetivo único - Porcentaje del asistente + Porcentaje en Calculadora Acción de Toque Complicación Unicode en complicaciones Versión: Más ajustes de la esfera del reloj Mira en la configuración de la esfera del reloj, por favor Objetivo Temporal - Asistente + Calculadora + Calc + Tratamiento + Trata Bolo - Carbohidratos + Carbos Configuración Estado Re-sincronizar @@ -74,13 +80,22 @@ Ninguno Por defecto Menú + XL Duración + Objetivo Temporal Solicitado + Asistente Rápido Solicitado + Tratamiento Solicitado + Bolo Solicitado + Calculadora Solicitada + Llenado Solicitado + Carbohidratos Solicitados + CPP Solicitado Objetivo Bajo Alto Carbohidratos Porcentaje - Inicio [min] + Iniciar [min] Duración [h] Insulina Botón 1 @@ -142,4 +157,13 @@ Durante la carga Modo siempre encendido Siempre encendido y cargando + Comiendo + Hipo + Actividad + Manual + Cancelar + Ninguno + No hay configuración disponible + Controles Wear desactivados + No hay datos disponibles diff --git a/wear/src/main/res/values-fr-rFR/strings.xml b/wear/src/main/res/values-fr-rFR/strings.xml index bfcb59f396..ec412c0e60 100644 --- a/wear/src/main/res/values-fr-rFR/strings.xml +++ b/wear/src/main/res/values-fr-rFR/strings.xml @@ -11,6 +11,9 @@ AAPS (Cockpit) AAPS (Steampunk) AAPS (Digital) + AAPS (Actions) + AAPS(Cible Temp) + AAPS(Assistant rapide) Pas de données ! Données anciennes! Depuis %1$s @@ -54,10 +57,10 @@ Historique (Cercle) Historique Léger (Cercle) Animations (Cercle) - Assistant dans Menu + Assistant dans le menu Amorcer dans Menu Cible Unique - Assistant Pourcentage + Pourcentage de l\'Assistant Action Appui Complication Unicode dans Complications Version: @@ -65,8 +68,11 @@ Veuillez regardez dans la configuration du cadran. Cible Temp Assistant + Assist. + Traitement + Trait. Bolus - eGlucides + Glucides Paramètres États Re-sync @@ -74,22 +80,31 @@ Aucun Défaut Menu - durée - cible - bas - haut - glucides - pourcentage - début [min] - durée [h] - insuline + XL + Durée + Cible Temp demandée + Assistant rapide demandé + Traitement demandé + Bolus demandé + Calcul demandé + Remplissage demandé + Glucides requis + Profil demandé + Cible + Bas + Élevé + Glucides + Pourcentage + Début [min] + Durée [h] + Insuline Quantité 1 Quantité 2 Quantité 3 Quantité libre CONFIRMER décalage - bolus + Bolus Bolus en cours Click pour annuler ANNULER BOLUS @@ -142,4 +157,13 @@ Pendant la charge Toujours allumé Toujours allumé et pendant la charge + Repas + Hypo + Activité + Manuel + Annuler + Aucun + Aucune configuration disponible + Contrôles Wear désactivés + Aucune donnée disponible diff --git a/wear/src/main/res/values-it-rIT/strings.xml b/wear/src/main/res/values-it-rIT/strings.xml index a249868946..b0f0da7a9a 100644 --- a/wear/src/main/res/values-it-rIT/strings.xml +++ b/wear/src/main/res/values-it-rIT/strings.xml @@ -54,19 +54,15 @@ Ring History Light Ring History Animazioni - Wizard in Menu Carica in Menu Target singolo - Percentuale Wizard Complication Tap Action Unicode in Complications Versione: più impostazioni watchface Controlla configurazione watchface. TempT - Wizard Bolo - eCarb Impostazioni Stato Re-Sincronizza @@ -74,22 +70,12 @@ Nessuno Default Menu - durata - target - basso - alto - CHO - percentuale - avvio [min] - durata [h] - insulina Preset 1 Preset 2 Preset 3 Quantità libera CONFERMA timeshift - bolo Progresso bolo premi per cancellare CANCELLA BOLO diff --git a/wear/src/main/res/values-iw-rIL/strings.xml b/wear/src/main/res/values-iw-rIL/strings.xml index 38b5e588d2..b814e9b1fb 100644 --- a/wear/src/main/res/values-iw-rIL/strings.xml +++ b/wear/src/main/res/values-iw-rIL/strings.xml @@ -54,19 +54,15 @@ היסטוריית צלצולים היסטוריה של טבעת אור אנימציות - אשף בתפריט תיחול בתפריט מטרה יחידה - אחוז אשף פעולת הקשה על סיבוך יוניקוד בסיבוכים גירסה: עוד הגדרות פני שעון עיינו בהגדרות פני השעון בבקשה. מטרה זמנית - אשף בולוס - פחמימות ממושכות הגדרות סטטוס סנכרן מחדש @@ -74,22 +70,12 @@ ללא ברירת מחדל תפריט - משך - מטרה - נמוך - גבוה - פחמימות - אחוז - התחלה [min] - משך [h] - אינסולין הגדרה מראש 1 הגדרה מראש 2 הגדרה מראש 3 כמות חופשית אישור היסט זמן - בולוס התקדמות הבולוס לחצו לביטול ביטול בולוס @@ -138,6 +124,7 @@ התקדמות בולוס שקטה התקדמות הבולוס וביטול התקדמות הבולוס וביטול עם פחות רטט + כבוי בזמן טעינה מצב דלוק תמיד דלוק תמיד וטוען diff --git a/wear/src/main/res/values-ko-rKR/strings.xml b/wear/src/main/res/values-ko-rKR/strings.xml index 90fbedc84f..5549a643b4 100644 --- a/wear/src/main/res/values-ko-rKR/strings.xml +++ b/wear/src/main/res/values-ko-rKR/strings.xml @@ -54,19 +54,15 @@ 원형 이력 연한 원형 이력 애니메이션 - 메뉴에서 마법사 메뉴에서 교체 단일 목표 - 마법사 퍼센트 컴플리케이션 탭 동작 컴플리케이션에서 유니코드 사용 버전: 더 다양한 워치페이스 설정 워치페이스 설정을 확인하십시오. 임시목표 - 마법사 Bolus - 확장탄수화물 설정 상태 재동기화 @@ -74,22 +70,12 @@ 없음 기본 메뉴 - 기간 - 목표 - 하한값 - 상한값 - 탄수화물 - 퍼센트 - 시작 [min] - 기간 [h] - 인슐린 프리셋 1 프리셋 2 프리셋 3 양 제한없음 확인 시간이동 - Bolus Bolus 주입 중 눌러서 취소하기 BOLUS 취소 diff --git a/wear/src/main/res/values-lt-rLT/strings.xml b/wear/src/main/res/values-lt-rLT/strings.xml index 5535155294..cce52f97ff 100644 --- a/wear/src/main/res/values-lt-rLT/strings.xml +++ b/wear/src/main/res/values-lt-rLT/strings.xml @@ -54,19 +54,15 @@ Glikemijos istorija Glikemijos istorija - šviesi Animacijos - Meniu vedlys Užpildyti per meniu Pavienis tikslas - Vedlys su % Elementų skirtuko veiksmai Unikodas elementuose Versija: Daugiau laikrodžio ekrano nustatymų Prašom žiūrėti Watchface konfigūraciją. LaikinasTikslas - Vedlys Bolusas - iAV Parametrai Būsena Suderinti dar kartą @@ -74,22 +70,12 @@ Nėra Numatytasis Meniu - trukmė - tikslas - žemas - aukštas - AV - procentais - pradėti [min] - trukmė [h] - insulinas Ruošinys 1 Ruošinys 2 Ruošinys 3 Užpildymo kiekis PATVIRTINTI laiko postūmis - bolusas Leidžiamas bolusas paspauskite atšaukimui ATŠAUKTI BOLUSĄ diff --git a/wear/src/main/res/values-nl-rNL/strings.xml b/wear/src/main/res/values-nl-rNL/strings.xml index 3d4b2729e4..d839d1900f 100644 --- a/wear/src/main/res/values-nl-rNL/strings.xml +++ b/wear/src/main/res/values-nl-rNL/strings.xml @@ -11,6 +11,9 @@ AAPS(Cockpit) AAPS(Steampunk) AAPS (DigitalStyle) + AAPS(Acties) + AAPS(Tijdelijk Streefdoel) + AAPS(Quick Wizard) Geen gegevens! Oude gegevens! Sinds %1$s @@ -54,19 +57,22 @@ Ring geschiedenis Lichte ring geschiedenis Animaties - Wizard in menu + Calculator in Menu Ontlucht/vul in menu Enkel streefdoel - Wizardpercentage + Calculator percentage Complicatie tik voor actie Unicode in complicaties Versie: meer Watchface instellingen Kijk naar de Watchface configuratie, alsjeblieft. TijdStreefd - Wizard + Calculator + Calc + Behandeling + Behandel Bolus - eCarb + Koolhydraten Instellingen Status Opnieuw synchroniseren @@ -74,22 +80,31 @@ Geen Standaard Menu - tijdsduur - doel - laag - hoog - khd - percentage - start [min] - duur [h] - insuline + XL + Duur + Tijdelijk streefdoel aangevraagd + QuickWizard aangevraagd + Behandeling aangevraagd + Bolus aangevraagd + Berekening aangevraagd + Vullen aangevraagd + Koolhydraten aangevraagd + CPP aangevraagd + Doel + Laag + Hoog + Koolhydraten + Percentage + Start [min] + Duur [h] + Insuline Voorinstelling 1 Voorinstelling 2 Voorinstelling 3 Vrije hoeveelheid BEVESTIGEN tijdsverschuiving - bolus + Bolus Bolus voortgang druk om te annuleren BOLUS ANNULEREN @@ -142,4 +157,13 @@ Tijdens Opladen Altijd Aan modus Altijd Aan en Opladen + Eten + Hypo + Activiteit + Handmatig + Afbreken + Geen + Geen configuratie beschikbaar + Wear OS besturing uitgeschakeld + Geen data beschikbaar diff --git a/wear/src/main/res/values-no-rNO/strings.xml b/wear/src/main/res/values-no-rNO/strings.xml index 7f3e243125..aa396bcff1 100644 --- a/wear/src/main/res/values-no-rNO/strings.xml +++ b/wear/src/main/res/values-no-rNO/strings.xml @@ -11,6 +11,9 @@ AAPS(Cockpit) AAPS(Steampunk) AAPS(DigitalStyle) + AAPS(Actions) + AAPS(Temp Target) + AAPS(Quick Wizard) Ingen data! Gamle data! Siden %1$s @@ -54,19 +57,22 @@ Ringe historikk Lys ringe historikk Animasjoner - Veiviser i meny + Kalkulator i Meny Prime i menyen Enkel måleverdi - Veiviser prosent + Kalkulator prosent Komplikasjon trykk handling Unicode ikomplikasjoner Versjon: flere urskive innstillinger Vennligst sjekk urskive innstillinger. TempT - Veiviser + Kalkulator + Kalk + Behandling + Behandle Bolus - eKarbo + Karbo Innstillinger Status Re-synk @@ -74,22 +80,31 @@ Ingen Standard Meny - varighet - målverdi - lav - høy - karbo - prosent - start [min] - varighet [h] - insulin + XL + Varighet + Temp target forespurt + Quick Wizard forespurt + Behandling forespurt + Bolus forespurt + Beregning forespurt + Fylling forespurt + Karbo forespurt + CPP forespurt + Mål + Lav + Høy + Karbo + Prosent + Start [min] + Varighet [h] + Insulin Forhåndsinnstilling 1 Forhåndsinnstilling 2 Forhåndsinnstilling 3 Valgfri mengde BEKREFT tidsforskyving - bolus + Bolus Bolus fremdrift trykk for å avbryte AVBRYT BOLUS @@ -142,4 +157,13 @@ Under lading Alltid På modus Alltid på under lading + Spising + Hypo + Aktivitet + Manuell + Avbryt + Ingen + Ingen konfigurasjon tilgjengelig + Wear kontroller deaktivert + Ingen data tilgjengelig diff --git a/wear/src/main/res/values-pl-rPL/strings.xml b/wear/src/main/res/values-pl-rPL/strings.xml index 95c9dc48d8..bcf10c8b33 100644 --- a/wear/src/main/res/values-pl-rPL/strings.xml +++ b/wear/src/main/res/values-pl-rPL/strings.xml @@ -54,10 +54,8 @@ Historia glikemi Dyskretniejsza historia Animacje - Kalkulator w Menu Wypełnianie w menu Pojedyńcza wartość Celu - Kalkulator z korektą w % Akcja po kliknięciu komplikacji Unicode w Komplikacjach Wersja: @@ -65,8 +63,8 @@ Proszę, zajrzyj do konfiguracji zegarka. CelTymcz. Kalkulator + Kalk Bolus - eWęgle Ustawienia Status Ponowna synchronizacja @@ -74,22 +72,21 @@ Brak Domyślnie Menu - czas trwania - cel - nisko - wysoko - węglow. - procent - start [min] - czas trwania [g] - insulina + Cel + Niski + Wysoki + Węglowodany + Procent + Start [min] + Czas trwania [h] + Insulina Ustawienie 1 Ustawienie 2 Ustawienie 3 Podana wartość POTWIERDŹ przesunięcie czasu - bolus + Bolus Postęp bolusa naciśnij aby anulować ANULUJ BOLUS @@ -142,4 +139,10 @@ Podczas ładowania Tryb Always On Always On i ładowanie + Posiłek + Hipo + Ćwiczenia + Ręczne + Anuluj + Konfiguracja nie jest dostępna diff --git a/wear/src/main/res/values-pt-rBR/strings.xml b/wear/src/main/res/values-pt-rBR/strings.xml index 5e1e59d076..d57abf2a8c 100644 --- a/wear/src/main/res/values-pt-rBR/strings.xml +++ b/wear/src/main/res/values-pt-rBR/strings.xml @@ -53,39 +53,25 @@ Anel Histórico Anel Suave Histórico Animações - Assistente no Menu Purgar no Menu Alvo Único - Assistente Percentagem Complicação de Toque Unicode em Complicações Versão: AlvoT - Assistente Bólus - eCarb Definições Estado Purgar/Preencher Nenhum Padrão Menu - duração - alvo - hipo - hiper - hidratos - percentagem - iniciar [min] - duração [h] - insulina Predefinição 1 Predefinição 2 Predefinição 3 Valor livre CONFIRMAR alteração turno - bólus Bomba Loop CPP diff --git a/wear/src/main/res/values-pt-rPT/strings.xml b/wear/src/main/res/values-pt-rPT/strings.xml index cce020a285..5d10f2aba4 100644 --- a/wear/src/main/res/values-pt-rPT/strings.xml +++ b/wear/src/main/res/values-pt-rPT/strings.xml @@ -54,19 +54,15 @@ Anel Histórico Anel Suave Histórico Animações - Assistente no Menu Purgar no Menu Alvo Único - Assistente Percentagem Complicação de Toque Unicode em Complicações Versão: mais definições do Mostrador Verifique a configuração do mostrador, por favor. AlvoT - Assistente Bólus - eCarb Definições Estado Re-Sincronizar @@ -74,22 +70,12 @@ Nenhum Padrão Menu - duração - alvo - hipo - hiper - hidratos - percentagem - iniciar [min] - duração [h] - insulina Predefinição 1 Predefinição 2 Predefinição 3 Valor livre CONFIRMAR Deslocamento temporal - bólus Progresso do Bólus pressione para cancelar CANCELAR BÓLUS diff --git a/wear/src/main/res/values-ro-rRO/strings.xml b/wear/src/main/res/values-ro-rRO/strings.xml index 5af0f23cb6..6ec5eb2dfb 100644 --- a/wear/src/main/res/values-ro-rRO/strings.xml +++ b/wear/src/main/res/values-ro-rRO/strings.xml @@ -54,19 +54,15 @@ Inel istoric Inel istoric simplu Animații - Asistent în meniu Amorsare în meniu Țintă unică - Procent asistent Acţiuni pentru complicaţii Unicode în complicații Versiune: mai multe setări Watchface Uitaţi-vă în configurarea Watchface, vă rugăm. ŢintăTemporară - Asistent Bolus - eCarb Setări Stare Re-Sincronizare @@ -74,22 +70,12 @@ Nimic Implicit Meniu - durată - țintă - hipo - hiper - carbohidrați - procentaj - start [min] - durată [h] - insulină Presetare 1 Presetare 2 Presetare 3 Cantitate liberă CONFIRMARE timp - bolus Progres bolus apasă pentru a anula ANULARE BOLUS diff --git a/wear/src/main/res/values-ru-rRU/strings.xml b/wear/src/main/res/values-ru-rRU/strings.xml index c99a8b6096..ffddf2b5f6 100644 --- a/wear/src/main/res/values-ru-rRU/strings.xml +++ b/wear/src/main/res/values-ru-rRU/strings.xml @@ -54,19 +54,15 @@ Показывать историю в кольце Показывать историю в кольце менее подробно Анимация - Мастер в меню Первичное заполнение в меню Единичная цель - Процент мастера Действия при нажатии кнопки расширений Юникод в репликации Версия: еще настройки циферблатов Смотрите конфигурацию циферблата. ВремЦ - Мастер настройки Болюс - eCarbs/производные углеводы Настройки Состояние Синхронизировать повторно @@ -74,22 +70,12 @@ Не показывать По умолчанию Menu - продолжительность - целевое значение ГК: - низкий - высокий - углеводы - процент - начало [min] - продолжительность [h] - инсулин Предустановка 1 Предустановка 2 Предустановка 3 Произвольное количество ПОДТВЕРДИТЬ сдвиг по времени - болюс Подается болюс нажмите для отмены ОТМЕНИТЬ БОЛЮС diff --git a/wear/src/main/res/values-sk-rSK/strings.xml b/wear/src/main/res/values-sk-rSK/strings.xml index c07cba3847..8d2708878e 100644 --- a/wear/src/main/res/values-sk-rSK/strings.xml +++ b/wear/src/main/res/values-sk-rSK/strings.xml @@ -11,6 +11,9 @@ AAPS(Cockpit) AAPS (Steampunk) AAPS(DigitalStyle) + AAPS (Akcie) + AAPS(Dočasný cieľ) + AAPS(Rýchly bolus) Žiadne dáta! Zastaralé dáta! Od %1$s @@ -54,19 +57,22 @@ História glykémií - kruh História glykémií - svetlý kruh Animácie - Sprievodca v nastaveniach + Kalkulačka v nastaveniach Plnenie v nastaveniach Jeden cieľ - Sprievodca percentuálne + Percento kalkulačky Zadaj komplikáciu Unicode v komplikáciach Verzia: ďalšie nastavenia Watchface Pozrite sa prosím do konfigurácie Watchface. TempT - Sprievodca + Kalkulačka + Kalk + Ošetrenie + Ošetr Bolus - eCarbs + Sacharidy Nastavenia Stav Opätovne synchronizovať @@ -74,22 +80,31 @@ Žiadny Štandardný Ponuka - trvanie - cieľ - nízka - vysoká - sacharidy + XL + Trvanie + Požadovaný dočasný cieľ + Požadovaný rýchly bolus + Požadované ošetrenie + Požadovaný bolus + Požadovaná kalkulačka + Požadované plnenie + Požadované sacharidy + Požadovaný profil + Cieľ + Nízka + Vysoká + Sacharidy Percento - začiatok [min] - trvanie [h] - inzulín + Začiatok [min] + Trvanie [h] + Inzulín Predvoľba 1 Predvoľba 2 Predvoľba 3 Ľubovoľné množstvo POTVRDIŤ časový posun - bolus + Bolus Priebeh podávania bolusu stlačením tlačidla zrušíte akciu ZRUŠIŤ BOLUS @@ -142,4 +157,13 @@ Počas nabíjania Mód vždy zapnuté Vždy zapnuté a nabíjanie + Jedlo + Hypo + Aktivita + Ručne + Zrušiť + Žiadny + Nie je dostupná žiadna konfigurácia + Ovládanie hodinkami vypnuté + Žiadne údaje nie sú k dispozícii diff --git a/wear/src/main/res/values-sv-rSE/strings.xml b/wear/src/main/res/values-sv-rSE/strings.xml index 441afd92cb..216481cb4b 100644 --- a/wear/src/main/res/values-sv-rSE/strings.xml +++ b/wear/src/main/res/values-sv-rSE/strings.xml @@ -11,6 +11,9 @@ AAPS (Cockpit) AAPS (Steampunk) AAPS (DigitalStyle) + AAPS(Åtgärder) + AAPS(Temp-mål) + AAPS(Snabbsteg) Inga data! Gamla data! Sedan %1$s @@ -54,19 +57,22 @@ Ringhistorik Ljus ringhistorik Animationer - Guide i menyn + Kalkylator i menyn Förfyllning i menyn Enkelt målvärde - Procent av guiden + Kalkylator Procent Åtgärd för komplikation \"tryck\" Unicode i komplikationer Version: fler watchface-inställningar Kontrollera watchface-konfigurationen, tack. Tempmål - Guide + Kalkylator + Kalk + Behandling + Beh Bolus - eCarb + KH Inställningar Status Synkronisera om @@ -74,22 +80,31 @@ Ingen Standardinställning Meny - duration - målvärde - låg - hög + Snabb + Duration + Temp-mål begärt + Snabbsteg begärd + Behandling begärd + Bolus begärd + Kalkylator begärd + Påfyllning begärd + Kolhydrater begärda + CPP begärd + Mål + Låg + Hög KH - procent - start [min] - varaktighet [tim] - insulin + Procent + Start [min] + Duration [tim] + Insulin Förinställning 1 Förinställning 2 Förinställning 3 Valfri mängd BEKRÄFTA tidsförskjutning - bolus + Bolus Bolusförlopp tryck för att avbryta AVBRYT BOLUS @@ -142,4 +157,13 @@ Vid laddning Alltid På-läge Alltid På och vid laddning + Äter + Hypo + Träning + Manuellt + Avbryt + Inget + Ingen konfiguration tillgänglig + Wear-kontroller inaktiverade + Ingen data tillgänglig diff --git a/wear/src/main/res/values-tr-rTR/strings.xml b/wear/src/main/res/values-tr-rTR/strings.xml index d74a2c5106..22329c55f9 100644 --- a/wear/src/main/res/values-tr-rTR/strings.xml +++ b/wear/src/main/res/values-tr-rTR/strings.xml @@ -11,6 +11,9 @@ AAPS(Cockpit) AAPS(Steampunk) AAPS(DijitalStil) + AAPS(Eylemler) + AAPS(Geçici Hedef) + AAPS(Hızlı Asistan) Veri yok! Eski veri! %1$s den beri @@ -54,19 +57,22 @@ Zil Geçmişi Düşük zil Geçmişi Animasyonlar - Menüdeki Sihirbaz + Menüdeki Hesap Makinesi Menüden Başlatma Tek hedef - Sihirbaz Yüzdesi + Hesap Makinesi Yüzdesi Komplikasyon Dokunma Eylemi Komplikasyonlarda Unicode Versiyon: daha çok saatarayüz ayarı Lütfen, Saatarayüzü yapılandırmasına bakın. GeçiciH - Sihirbaz + Hesap makinesi + Hesap + Tedavi + Tedavi Bolus - eCarb + Karbonhidrat Ayarlar Durum Yen-Senkr @@ -74,22 +80,31 @@ Hiçbiri Varsayılan Menü - süre - hedef - düşük - yüksek - karbonhidrat - yüzde - başlat [min] - süre [h] - insülin + XL + Süre + Geçici hedef talebi + Hızlı asistan talebi + Tedavi talebi + Bolus talebi + Hesaplama talebi + Doldurma talebi + Karonhidrat talebi + CPP talebi + Hedef + Düşük + Yüksek + Karbonhidrat + Yüzde + Başlat [min] + Süre [h] + İnsülin Ön ayar 1 Ön ayar 2 Ön ayar 3 Serbest miktar ONAYLA vardiya - bolus + Bolus Bolus İlerlemesi iptal etmek için basın BOLUS İPTAL ET @@ -142,4 +157,13 @@ Şarj Olurken Her Zaman Açık Modu Her Zaman Açık ve Şarj Oluyor + Yemek + Hipo + Aktivite + Manuel + İptal + Hiçbiri + Mevcut yapılandırma yok + Saat kontrolleri devre dışı + Veri yok From cb3bb583196f1c139903daee42c20523d79a12ba Mon Sep 17 00:00:00 2001 From: Andries Smit Date: Wed, 23 Feb 2022 10:11:14 +0100 Subject: [PATCH 25/40] fix: treatments persist selection on scrolling --- .../fragments/TreatmentsBolusCarbsFragment.kt | 62 ++++++++++--------- .../fragments/TreatmentsCareportalFragment.kt | 47 +++++++------- .../TreatmentsExtendedBolusesFragment.kt | 39 +++++++----- .../TreatmentsProfileSwitchFragment.kt | 42 +++++++------ .../fragments/TreatmentsTempTargetFragment.kt | 47 +++++++------- .../TreatmentsTemporaryBasalsFragment.kt | 44 +++++++------ 6 files changed, 157 insertions(+), 124 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt index 5840cc1a35..1323b23113 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsBolusCarbsFragment.kt @@ -3,10 +3,13 @@ package info.nightscout.androidaps.activities.fragments import android.annotation.SuppressLint import android.graphics.Paint import android.os.Bundle +import android.util.Log +import android.util.SparseArray import android.view.* import android.widget.CompoundButton import android.view.ActionMode import androidx.appcompat.widget.Toolbar +import androidx.core.util.forEach import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment @@ -68,6 +71,10 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { @Inject lateinit var repository: AppRepository @Inject lateinit var activePlugin: ActivePlugin + private var _binding: TreatmentsBolusCarbsFragmentBinding? = null + // This property is only valid between onCreateView and onDestroyView. + private val binding get() = _binding!! + class MealLink( val bolus: Bolus? = null, val carbs: Carbs? = null, @@ -75,17 +82,11 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { ) private val disposable = CompositeDisposable() - private val millsToThePast = T.days(30).msecs() - private var _binding: TreatmentsBolusCarbsFragmentBinding? = null - - // This property is only valid between onCreateView and onDestroyView. - private val binding get() = _binding!! - private var selectedItems: MutableList = mutableListOf() + private var selectedItems: SparseArray = SparseArray() private var showInvalidated = false private var removeActionMode: ActionMode? = null - private var toolbar: Toolbar? = null override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = @@ -253,21 +254,22 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { holder.binding.carbsPump.visibility = (carbs.interfaceIDs.pumpId != null).toVisibility() holder.binding.carbsInvalid.visibility = carbs.isValid.not().toVisibility() } - - val onChange = CompoundButton.OnCheckedChangeListener { _, value -> - if (value) { - selectedItems.add(ml) - } else { - selectedItems.remove(ml) - } - removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size) - } - holder.binding.cbBolusRemove.visibility = ((ml.bolus?.isValid == true) && removeActionMode != null).toVisibility() - holder.binding.cbBolusRemove.setOnCheckedChangeListener(onChange) - + holder.binding.cbBolusRemove.visibility = (ml.bolus?.isValid == true && removeActionMode != null).toVisibility() holder.binding.cbCarbsRemove.visibility = (ml.carbs?.isValid == true && removeActionMode != null).toVisibility() - holder.binding.cbCarbsRemove.setOnCheckedChangeListener(onChange) - + if (removeActionMode != null) { + val onChange = CompoundButton.OnCheckedChangeListener { _, value -> + if (value) { + selectedItems.put(position, ml) + } else { + selectedItems.remove(position) + } + removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size()) + } + holder.binding.cbBolusRemove.setOnCheckedChangeListener(onChange) + holder.binding.cbBolusRemove.isChecked = selectedItems.get(position) != null + holder.binding.cbCarbsRemove.setOnCheckedChangeListener(onChange) + holder.binding.cbCarbsRemove.isChecked = selectedItems.get(position) != null + } holder.binding.calculation.tag = ml val nextTimestamp = if (mealLinks.size != position + 1) timestamp(mealLinks[position + 1]) else 0L holder.binding.delimiter.visibility = dateUtil.isSameDay(timestamp(ml), nextTimestamp).toVisibility() @@ -425,8 +427,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) - selectedItems = mutableListOf() - mode.title = rh.gs(R.string.count_selected, selectedItems.size) + selectedItems.clear() + mode.title = rh.gs(R.string.count_selected, selectedItems.size()) binding.recyclerview.adapter?.notifyDataSetChanged() return true } @@ -437,7 +439,6 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { return when (item.itemId) { R.id.remove_selected -> { removeSelected() - mode.finish() true } @@ -452,8 +453,8 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { } private fun getConfirmationText(): String { - if (selectedItems.size == 1) { - val mealLink = selectedItems.first() + if (selectedItems.size() == 1) { + val mealLink = selectedItems.valueAt(0) val bolus = mealLink.bolus if (bolus != null) return rh.gs(R.string.configbuilder_insulin) + ": " + rh.gs(R.string.formatinsulinunits, bolus.amount) + "\n" + @@ -463,14 +464,14 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { return rh.gs(R.string.carbs) + ": " + rh.gs(R.string.format_carbs, carbs.amount.toInt()) + "\n" + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(carbs.timestamp) } - return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) + return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size()) } fun removeSelected() { - if (selectedItems.size > 0) + if (selectedItems.size() > 0) activity?.let { activity -> OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { - selectedItems.forEach { ml -> + selectedItems.forEach {key, ml -> ml.bolus?.let { bolus -> uel.log( Action.BOLUS_REMOVED, Sources.Treatments, @@ -496,7 +497,10 @@ class TreatmentsBolusCarbsFragment : DaggerFragment() { ) } } + removeActionMode?.finish() }) } + else + removeActionMode?.finish() } } diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt index b2230d9caa..d2069a504b 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsCareportalFragment.kt @@ -1,9 +1,11 @@ package info.nightscout.androidaps.activities.fragments import android.os.Bundle +import android.util.SparseArray import android.view.* import android.view.ActionMode import androidx.appcompat.widget.Toolbar +import androidx.core.util.forEach import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment @@ -56,18 +58,17 @@ class TreatmentsCareportalFragment : DaggerFragment() { @Inject lateinit var repository: AppRepository @Inject lateinit var uel: UserEntryLogger - private val disposable = CompositeDisposable() + private var _binding: TreatmentsCareportalFragmentBinding? = null + // This property is only valid between onCreateView and onDestroyView. + private val binding get() = _binding!! + private val disposable = CompositeDisposable() private val millsToThePast = T.days(30).msecs() - private var selectedItems: MutableList = mutableListOf() + private var selectedItems: SparseArray = SparseArray() private var showInvalidated = false private var toolbar: Toolbar? = null private var removeActionMode: ActionMode? = null - private var _binding: TreatmentsCareportalFragmentBinding? = null - - // This property is only valid between onCreateView and onDestroyView. - private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = TreatmentsCareportalFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root @@ -172,13 +173,16 @@ class TreatmentsCareportalFragment : DaggerFragment() { holder.binding.note.text = therapyEvent.note holder.binding.type.text = translator.translate(therapyEvent.type) holder.binding.cbRemove.visibility = (therapyEvent.isValid && removeActionMode != null).toVisibility() - holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> - if (value) { - selectedItems.add(therapyEvent) - } else { - selectedItems.remove(therapyEvent) + if (removeActionMode != null) { + holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> + if (value) { + selectedItems.put(position, therapyEvent) + } else { + selectedItems.remove(position) + } + removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size()) } - removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size) + holder.binding.cbRemove.isChecked = selectedItems.get(position) != null } val nextTimestamp = if (therapyList.size != position + 1) therapyList[position + 1].timestamp else 0L holder.binding.delimiter.visibility = dateUtil.isSameDay(therapyEvent.timestamp, nextTimestamp).toVisibility() @@ -243,8 +247,8 @@ class TreatmentsCareportalFragment : DaggerFragment() { override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) - selectedItems = mutableListOf() - mode.title = rh.gs(R.string.count_selected, selectedItems.size) + selectedItems.clear() + mode.title = rh.gs(R.string.count_selected, selectedItems.size()) binding.recyclerview.adapter?.notifyDataSetChanged() return true } @@ -255,7 +259,6 @@ class TreatmentsCareportalFragment : DaggerFragment() { return when (item.itemId) { R.id.remove_selected -> { removeSelected() - mode.finish() true } @@ -270,20 +273,20 @@ class TreatmentsCareportalFragment : DaggerFragment() { } private fun getConfirmationText(): String { - if (selectedItems.size == 1) { - val therapyEvent = selectedItems.first() + if (selectedItems.size() == 1) { + val therapyEvent = selectedItems.valueAt(0) return rh.gs(R.string.eventtype) + ": " + translator.translate(therapyEvent.type) + "\n" + rh.gs(R.string.notes_label) + ": " + (therapyEvent.note ?: "") + "\n" + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(therapyEvent.timestamp) } - return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) + return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size()) } private fun removeSelected() { - if (selectedItems.size > 0) + if (selectedItems.size() > 0) activity?.let { activity -> OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { - selectedItems.forEach { therapyEvent -> + selectedItems.forEach { _, therapyEvent -> uel.log( Action.CAREPORTAL_REMOVED, Sources.Treatments, therapyEvent.note, ValueWithUnit.Timestamp(therapyEvent.timestamp), @@ -295,9 +298,11 @@ class TreatmentsCareportalFragment : DaggerFragment() { { aapsLogger.error(LTag.DATABASE, "Error while invalidating therapy event", it) } ) } - + removeActionMode?.finish() }) } + else + removeActionMode?.finish() } } diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt index c4ac1aff5b..57e766dc54 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsExtendedBolusesFragment.kt @@ -2,9 +2,11 @@ package info.nightscout.androidaps.activities.fragments import android.annotation.SuppressLint import android.os.Bundle +import android.util.SparseArray import android.view.* import android.view.ActionMode import androidx.appcompat.widget.Toolbar +import androidx.core.util.forEach import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment @@ -59,11 +61,10 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { @Inject lateinit var repository: AppRepository private var _binding: TreatmentsExtendedbolusFragmentBinding? = null - // This property is only valid between onCreateView and onDestroyView. private val binding get() = _binding!! - private var selectedItems: MutableList = mutableListOf() + private var selectedItems: SparseArray = SparseArray() private var showInvalidated = false private var removeActionMode: ActionMode? = null private var toolbar: Toolbar? = null @@ -149,13 +150,16 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { holder.binding.ratio.text = rh.gs(R.string.pump_basebasalrate, extendedBolus.rate) if (iob.iob != 0.0) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.insulin.currentTextColor) holder.binding.cbRemove.visibility = (extendedBolus.isValid && removeActionMode != null).toVisibility() - holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> - if (value) { - selectedItems.add(extendedBolus) - } else { - selectedItems.remove(extendedBolus) + if (removeActionMode != null) { + holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> + if (value) { + selectedItems.put(position, extendedBolus) + } else { + selectedItems.remove(position) + } + removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size()) } - removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size) + holder.binding.cbRemove.isChecked = selectedItems.get(position) != null } val nextTimestamp = if (extendedBolusList.size != position + 1) extendedBolusList[position + 1].timestamp else 0L holder.binding.delimiter.visibility = dateUtil.isSameDay(extendedBolus.timestamp, nextTimestamp).toVisibility() @@ -209,8 +213,8 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) - selectedItems = mutableListOf() - mode.title = rh.gs(R.string.count_selected, selectedItems.size) + selectedItems.clear() + mode.title = rh.gs(R.string.count_selected, selectedItems.size()) binding.recyclerview.adapter?.notifyDataSetChanged() return true } @@ -221,7 +225,6 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { return when (item.itemId) { R.id.remove_selected -> { removeSelected() - mode.finish() true } @@ -236,18 +239,19 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { } private fun getConfirmationText(): String { - if (selectedItems.size == 1) { + if (selectedItems.size() == 1) { + val bolus = selectedItems.valueAt(0) return rh.gs(R.string.extended_bolus) + "\n" + - "${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(selectedItems.first().timestamp)}" + "${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(bolus.timestamp)}" } - return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) + return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size()) } private fun removeSelected() { - if (selectedItems.size > 0) + if (selectedItems.size() > 0) activity?.let { activity -> OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { - selectedItems.forEach { extendedBolus -> + selectedItems.forEach { _, extendedBolus -> uel.log( Action.EXTENDED_BOLUS_REMOVED, Sources.Treatments, ValueWithUnit.Timestamp(extendedBolus.timestamp), @@ -260,7 +264,10 @@ class TreatmentsExtendedBolusesFragment : DaggerFragment() { { aapsLogger.debug(LTag.DATABASE, "Removed extended bolus $extendedBolus") }, { aapsLogger.error(LTag.DATABASE, "Error while invalidating extended bolus", it) }) } + removeActionMode?.finish() }) } + else + removeActionMode?.finish() } } diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt index 38073e13ad..2922ead097 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsProfileSwitchFragment.kt @@ -2,9 +2,11 @@ package info.nightscout.androidaps.activities.fragments import android.graphics.Paint import android.os.Bundle +import android.util.SparseArray import android.view.* import android.view.ActionMode import androidx.appcompat.widget.Toolbar +import androidx.core.util.forEach import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment @@ -61,17 +63,16 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { @Inject lateinit var uel: UserEntryLogger private var _binding: TreatmentsProfileswitchFragmentBinding? = null + // This property is only valid between onCreateView and onDestroyView. + private val binding get() = _binding!! private val disposable = CompositeDisposable() - private val millsToThePast = T.days(30).msecs() - private var selectedItems: MutableList = mutableListOf() + private var selectedItems: SparseArray = SparseArray() private var showInvalidated = false private var removeActionMode: ActionMode? = null private var toolbar: Toolbar? = null - // This property is only valid between onCreateView and onDestroyView. - private val binding get() = _binding!! override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = TreatmentsProfileswitchFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root @@ -198,13 +199,16 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { holder.binding.invalid.visibility = profileSwitch.isValid.not().toVisibility() holder.binding.duration.visibility = (profileSwitch.duration != 0L && profileSwitch.duration != null).toVisibility() holder.binding.cbRemove.visibility = (removeActionMode != null && profileSwitch is ProfileSealed.PS).toVisibility() - holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> - if (value) { - selectedItems.add(profileSwitch) - } else { - selectedItems.remove(profileSwitch) + if (removeActionMode != null) { + holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> + if (value) { + selectedItems.put(position, profileSwitch) + } else { + selectedItems.remove(position) + } + removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size()) } - removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size) + holder.binding.cbRemove.isChecked = selectedItems.get(position) != null } holder.binding.clone.visibility = (profileSwitch is ProfileSealed.PS).toVisibility() holder.binding.spacer.visibility = (profileSwitch is ProfileSealed.PS).toVisibility() @@ -314,8 +318,8 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) - selectedItems = mutableListOf() - mode.title = rh.gs(R.string.count_selected, selectedItems.size) + selectedItems.clear() + mode.title = rh.gs(R.string.count_selected, selectedItems.size()) binding.recyclerview.adapter?.notifyDataSetChanged() return true } @@ -326,7 +330,6 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { return when (item.itemId) { R.id.remove_selected -> { removeSelected() - mode.finish() true } @@ -341,18 +344,18 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { } private fun getConfirmationText(): String { - if (selectedItems.size == 1) { - val profileSwitch = selectedItems.first() + if (selectedItems.size() == 1) { + val profileSwitch = selectedItems.valueAt(0) return rh.gs(R.string.careportal_profileswitch) + ": " + profileSwitch.profileName + "\n" + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(profileSwitch.timestamp) } - return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) + return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size()) } private fun removeSelected() { - if (selectedItems.size > 0) + if (selectedItems.size() > 0) activity?.let { activity -> OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { - selectedItems.forEach { profileSwitch -> + selectedItems.forEach { _, profileSwitch -> uel.log( Action.PROFILE_SWITCH_REMOVED, Sources.Treatments, profileSwitch.profileName, ValueWithUnit.Timestamp(profileSwitch.timestamp) @@ -363,7 +366,10 @@ class TreatmentsProfileSwitchFragment : DaggerFragment() { { aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it) } ) } + removeActionMode?.finish() }) } + else + removeActionMode?.finish() } } diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt index 846c1122e0..2144feb13e 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTempTargetFragment.kt @@ -2,8 +2,10 @@ package info.nightscout.androidaps.activities.fragments import android.annotation.SuppressLint import android.os.Bundle +import android.util.SparseArray import android.view.* import androidx.appcompat.widget.Toolbar +import androidx.core.util.forEach import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment @@ -65,19 +67,17 @@ class TreatmentsTempTargetFragment : DaggerFragment() { @Inject lateinit var uel: UserEntryLogger @Inject lateinit var repository: AppRepository - private val disposable = CompositeDisposable() + private var _binding: TreatmentsTemptargetFragmentBinding? = null + // This property is only valid between onCreateView and onDestroyView. + private val binding get() = _binding!! + private val disposable = CompositeDisposable() private val millsToThePast = T.days(30).msecs() - private var selectedItems: MutableList = mutableListOf() + private var selectedItems: SparseArray = SparseArray() private var showInvalidated = false private var toolbar: Toolbar? = null private var removeActionMode: ActionMode? = null - private var _binding: TreatmentsTemptargetFragmentBinding? = null - - // This property is only valid between onCreateView and onDestroyView. - private val binding get() = _binding!! - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = TreatmentsTemptargetFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root @@ -174,13 +174,16 @@ class TreatmentsTempTargetFragment : DaggerFragment() { holder.binding.ns.visibility = (tempTarget.interfaceIDs.nightscoutId != null).toVisibility() holder.binding.invalid.visibility = tempTarget.isValid.not().toVisibility() holder.binding.cbRemove.visibility = (tempTarget.isValid && removeActionMode != null).toVisibility() - holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> - if (value) { - selectedItems.add(tempTarget) - } else { - selectedItems.remove(tempTarget) + if (removeActionMode != null) { + holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> + if (value) { + selectedItems.put(position, tempTarget) + } else { + selectedItems.remove(position) + } + removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size()) } - removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size) + holder.binding.cbRemove.isChecked = selectedItems.get(position) != null } val sameDayPrevious = position > 0 && dateUtil.isSameDay(tempTarget.timestamp, tempTargetList[position - 1].timestamp) holder.binding.date.visibility = sameDayPrevious.not().toVisibility() @@ -211,10 +214,10 @@ class TreatmentsTempTargetFragment : DaggerFragment() { } private fun removeSelected() { - if (selectedItems.size > 0) + if (selectedItems.size() > 0) activity?.let { activity -> OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { - selectedItems.forEach { tempTarget -> + selectedItems.forEach { _, tempTarget -> uel.log( Action.TT_REMOVED, Sources.Treatments, ValueWithUnit.Timestamp(tempTarget.timestamp), @@ -228,8 +231,11 @@ class TreatmentsTempTargetFragment : DaggerFragment() { { aapsLogger.debug(LTag.DATABASE, "Removed temp target $tempTarget") }, { aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary target", it) }) } + removeActionMode?.finish() }) } + else + removeActionMode?.finish() } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { @@ -277,8 +283,8 @@ class TreatmentsTempTargetFragment : DaggerFragment() { override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) - selectedItems = mutableListOf() - mode.title = rh.gs(R.string.count_selected, selectedItems.size) + selectedItems.clear() + mode.title = rh.gs(R.string.count_selected, selectedItems.size()) binding.recyclerview.adapter?.notifyDataSetChanged() return true } @@ -289,7 +295,6 @@ class TreatmentsTempTargetFragment : DaggerFragment() { return when (item.itemId) { R.id.remove_selected -> { removeSelected() - mode.finish() true } @@ -304,12 +309,12 @@ class TreatmentsTempTargetFragment : DaggerFragment() { } private fun getConfirmationText(): String { - if (selectedItems.size == 1) { - val tempTarget = selectedItems.first() + if (selectedItems.size() == 1) { + val tempTarget = selectedItems.valueAt(0) return "${rh.gs(R.string.careportal_temporarytarget)}: ${tempTarget.friendlyDescription(profileFunction.getUnits(), rh)}\n" + dateUtil.dateAndTimeString(tempTarget.timestamp) } - return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) + return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size()) } } diff --git a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt index b24f062004..babd7f64c4 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/fragments/TreatmentsTemporaryBasalsFragment.kt @@ -1,8 +1,11 @@ package info.nightscout.androidaps.activities.fragments import android.os.Bundle +import android.util.Log +import android.util.SparseArray import android.view.* import androidx.appcompat.widget.Toolbar +import androidx.core.util.forEach import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import dagger.android.support.DaggerFragment @@ -62,16 +65,15 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { @Inject lateinit var repository: AppRepository private var _binding: TreatmentsTempbasalsFragmentBinding? = null + // This property is only valid between onCreateView and onDestroyView. + private val binding get() = _binding!! private val millsToThePast = T.days(30).msecs() - private var selectedItems: MutableList = mutableListOf() + private var selectedItems: SparseArray = SparseArray() private var showInvalidated = false private var toolbar: Toolbar? = null private var removeActionMode: ActionMode? = null - // This property is only valid between onCreateView and onDestroyView. - private val binding get() = _binding!! - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = TreatmentsTempbasalsFragmentBinding.inflate(inflater, container, false).also { _binding = it }.root @@ -192,13 +194,16 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { holder.binding.superBolusFlag.visibility = (tempBasal.type == TemporaryBasal.Type.SUPERBOLUS).toVisibility() if (abs(iob.basaliob) > 0.01) holder.binding.iob.setTextColor(rh.gc(R.color.colorActive)) else holder.binding.iob.setTextColor(holder.binding.duration.currentTextColor) holder.binding.cbRemove.visibility = (tempBasal.isValid && removeActionMode != null).toVisibility() - holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> - if (value) { - selectedItems.add(tempBasal) - } else { - selectedItems.remove(tempBasal) + if (removeActionMode != null) { + holder.binding.cbRemove.setOnCheckedChangeListener { _, value -> + if (value) { + selectedItems.put(position, tempBasal) + } else { + selectedItems.remove(position) + } + removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size()) } - removeActionMode?.title = rh.gs(R.string.count_selected, selectedItems.size) + holder.binding.cbRemove.isChecked = selectedItems.get(position) != null } val nextTimestamp = if (tempBasalList.size != position + 1) tempBasalList[position + 1].timestamp else 0L holder.binding.delimiter.visibility = dateUtil.isSameDay(tempBasal.timestamp, nextTimestamp).toVisibility() @@ -252,8 +257,8 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { override fun onCreateActionMode(mode: ActionMode, menu: Menu?): Boolean { mode.menuInflater.inflate(R.menu.menu_delete_selection, menu) - selectedItems = mutableListOf() - mode.title = rh.gs(R.string.count_selected, selectedItems.size) + selectedItems.clear() + mode.title = rh.gs(R.string.count_selected, selectedItems.size()) binding.recyclerview.adapter?.notifyDataSetChanged() return true } @@ -264,7 +269,6 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { return when (item.itemId) { R.id.remove_selected -> { removeSelected() - mode.finish() true } @@ -279,23 +283,22 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { } private fun getConfirmationText(): String { - if (selectedItems.size == 1) { - val tempBasal = selectedItems.first() + if (selectedItems.size() == 1) { + val tempBasal = selectedItems.valueAt(0) val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED val profile = profileFunction.getProfile(dateUtil.now()) if (profile != null) return "${if (isFakeExtended) rh.gs(R.string.extended_bolus) else rh.gs(R.string.tempbasal_label)}: ${tempBasal.toStringFull(profile, dateUtil)}\n" + "${rh.gs(R.string.date)}: ${dateUtil.dateAndTimeString(tempBasal.timestamp)}" } - return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size) + return rh.gs(R.string.confirm_remove_multiple_items, selectedItems.size()) } private fun removeSelected() { - // TODO check if item should not be delete val profile = profileFunction.getProfile(dateUtil.now()) == null - if (selectedItems.size > 0) + if (selectedItems.size() > 0) activity?.let { activity -> OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), getConfirmationText(), Runnable { - selectedItems.forEach { tempBasal -> + selectedItems.forEach {_, tempBasal -> var extendedBolus: ExtendedBolus? = null val isFakeExtended = tempBasal.type == TemporaryBasal.Type.FAKE_EXTENDED if (isFakeExtended) { @@ -327,7 +330,10 @@ class TreatmentsTemporaryBasalsFragment : DaggerFragment() { { aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) }) } } + removeActionMode?.finish() }) } + else + removeActionMode?.finish() } } From 0307789996c85d4014e75c6cb8c4ecb93a9d0674 Mon Sep 17 00:00:00 2001 From: Andries Smit Date: Wed, 23 Feb 2022 14:30:23 +0100 Subject: [PATCH 26/40] Fix hide super bolus calculation when not used --- .../java/info/nightscout/androidaps/dialogs/WizardDialog.kt | 4 +++- app/src/main/res/layout/dialog_wizard.xml | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt index d04d8c709a..a9c60573ef 100644 --- a/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/dialogs/WizardDialog.kt @@ -125,7 +125,9 @@ class WizardDialog : DaggerDialogFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { loadCheckedStates() processCobCheckBox() - binding.sbCheckbox.visibility = sp.getBoolean(R.string.key_usesuperbolus, false).toVisibility() + val useSuperBolus = sp.getBoolean(R.string.key_usesuperbolus, false) + binding.sbCheckbox.visibility = useSuperBolus.toVisibility() + binding.superBolusRow.visibility = useSuperBolus.toVisibility() binding.notesLayout.visibility = sp.getBoolean(R.string.key_show_notes_entry_dialogs, false).toVisibility() val maxCarbs = constraintChecker.getMaxCarbsAllowed().value() diff --git a/app/src/main/res/layout/dialog_wizard.xml b/app/src/main/res/layout/dialog_wizard.xml index 2ec56be3f9..4605b2117c 100644 --- a/app/src/main/res/layout/dialog_wizard.xml +++ b/app/src/main/res/layout/dialog_wizard.xml @@ -623,6 +623,7 @@ From e924c28542ac3e828a5c4294c5a506b0ce1f65aa Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 23 Feb 2022 19:05:55 +0100 Subject: [PATCH 27/40] Material style for app --- app/build.gradle | 2 +- app/src/main/AndroidManifest.xml | 7 +- .../nightscout/androidaps/MainActivity.kt | 2 +- .../activities/HistoryBrowseActivity.kt | 3 +- .../activities/ProfileHelperActivity.kt | 4 +- .../TreatmentsProfileSwitchFragment.kt | 63 ++++--- .../activities/QuickWizardListActivity.kt | 27 ++- .../overview/dialogs/EditQuickWizardDialog.kt | 6 +- .../profile/local/LocalProfileFragment.kt | 166 +++++++++++++----- .../alertDialogs/PrefImportSummaryDialog.kt | 4 +- .../alertDialogs/TwoMessagesAlertDialog.kt | 4 +- .../main/res/drawable/ic_local_activate.xml | 4 +- app/src/main/res/drawable/ic_local_reset.xml | 2 +- app/src/main/res/layout/actions_fragment.xml | 57 +++--- .../res/layout/actions_fragment_lowres.xml | 57 +++--- .../res/layout/activity_historybrowse.xml | 6 +- .../main/res/layout/activity_logsetting.xml | 10 +- app/src/main/res/layout/activity_main.xml | 9 +- app/src/main/res/layout/activity_stats.xml | 10 +- app/src/main/res/layout/close.xml | 2 +- .../res/layout/configbuilder_fragment.xml | 5 +- .../layout/dialog_alert_import_summary.xml | 8 +- app/src/main/res/layout/dialog_carbs.xml | 19 +- app/src/main/res/layout/dialog_fill.xml | 9 +- app/src/main/res/layout/dialog_insulin.xml | 11 +- app/src/main/res/layout/dialog_loop.xml | 6 +- app/src/main/res/layout/dialog_wizard.xml | 49 +++--- app/src/main/res/layout/dialog_wizardinfo.xml | 6 +- app/src/main/res/layout/food_item.xml | 2 +- .../main/res/layout/localprofile_fragment.xml | 95 +++++----- app/src/main/res/layout/loop_fragment.xml | 4 +- .../main/res/layout/maintenance_fragment.xml | 56 +++--- .../layout/number_picker_layout_vertical.xml | 12 +- .../res/layout/objectives_exam_fragment.xml | 24 +-- .../main/res/layout/objectives_fragment.xml | 4 +- app/src/main/res/layout/objectives_item.xml | 26 +-- app/src/main/res/layout/okcancel.xml | 13 +- .../main/res/layout/openapsama_fragment.xml | 4 +- .../res/layout/overview_notification_item.xml | 3 +- .../overview_quickwizardlist_activity.xml | 11 +- .../layout/overview_quickwizardlist_item.xml | 42 +++-- app/src/main/res/layout/tidepool_fragment.xml | 12 +- .../layout/treatments_bolus_carbs_item.xml | 2 +- app/src/main/res/layout/wear_fragment.xml | 8 +- app/src/main/res/values/colors.xml | 2 +- app/src/main/res/values/strings.xml | 3 +- app/src/main/res/values/styles.xml | 12 +- .../automation/elements/InputDateTime.kt | 4 +- .../general/automation/elements/InputTime.kt | 2 +- .../automation/elements/InputTimeRange.kt | 4 +- core/src/main/AndroidManifest.xml | 4 +- .../dialogs/DialogFragmentWithDate.kt | 6 +- .../androidaps/utils/alertDialogs/OKDialog.kt | 16 +- .../utils/protection/PasswordCheck.kt | 6 +- .../main/res/drawable/ic_actions_refill.xml | 12 +- core/src/main/res/drawable/ic_local_save.xml | 4 +- ...und.xml => material_button_background.xml} | 4 +- ...ected.xml => material_button_selected.xml} | 2 +- core/src/main/res/layout/close.xml | 2 +- .../main/res/layout/dialog_bolusprogress.xml | 3 +- core/src/main/res/layout/dialog_error.xml | 9 +- .../main/res/layout/number_picker_layout.xml | 9 +- core/src/main/res/layout/okcancel.xml | 5 +- core/src/main/res/values/colors.xml | 38 +++- core/src/main/res/values/layout.xml | 8 - core/src/main/res/values/styles.xml | 143 +++++++++------ dana/src/main/res/layout/danar_fragment.xml | 8 +- .../res/layout/danar_history_activity.xml | 7 +- .../layout/danar_user_options_activity.xml | 4 +- .../layout/danars_pairing_progress_dialog.xml | 3 +- .../main/res/layout/diaconn_g8_fragment.xml | 125 +++++++------ .../layout/diaconn_g8_history_activity.xml | 9 +- .../diaconn_g8_user_options_activity.xml | 12 +- diaconn/src/main/res/values/colors.xml | 2 - .../res/layout/activity_insight_alert.xml | 8 +- .../res/layout/activity_insight_pairing.xml | 9 +- .../activity_insight_pairing_information.xml | 3 +- .../res/layout/local_insight_fragment.xml | 9 +- .../main/res/layout/medtronic_fragment.xml | 139 +++++++++------ medtronic/src/main/res/xml/pref_medtronic.xml | 2 +- .../fragment/info/AttachPodFragment.kt | 2 +- .../activity/OmnipodWizardActivityBase.kt | 2 +- .../fragment/action/DeactivatePodFragment.kt | 2 +- .../omnipod_common_overview_buttons.xml | 12 +- ...pod_common_wizard_action_page_fragment.xml | 9 +- .../omnipod_common_wizard_nav_buttons.xml | 6 +- omnipod-eros/src/main/res/values/strings.xml | 1 - .../main/res/xml/omnipod_eros_preferences.xml | 2 +- rileylink/src/main/AndroidManifest.xml | 7 +- .../dialog/RileyLinkBLEConfigActivity.kt | 46 +++-- .../layout/riley_link_ble_config_activity.xml | 9 +- .../src/main/res/layout/rileylink_status.xml | 8 +- .../layout/rileylink_status_device_item.xml | 3 +- rileylink/src/main/res/values/strings.xml | 1 + 94 files changed, 953 insertions(+), 671 deletions(-) rename core/src/main/res/drawable/{mdtp_material_button_background.xml => material_button_background.xml} (54%) rename core/src/main/res/drawable/{mdtp_material_button_selected.xml => material_button_selected.xml} (86%) delete mode 100644 core/src/main/res/values/layout.xml diff --git a/app/build.gradle b/app/build.gradle index afd6151263..df720e4e89 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -109,7 +109,7 @@ android { defaultConfig { multiDexEnabled true versionCode 1500 - version "3.0.0.1-dev-a" + version "3.0.0.1-dev-b" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 92f076e434..a163b3729c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -64,6 +64,7 @@ @@ -75,8 +76,7 @@ - + + android:label="@string/title_activity_setup_wizard" /> OKDialog.showConfirmation(activity, rh.gs(R.string.removerecord), - rh.gs(R.string.careportal_profileswitch) + ": " + profileSwitch.profileName + - "\n" + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(profileSwitch.timestamp), Runnable { - uel.log(Action.PROFILE_SWITCH_REMOVED, Sources.Treatments, profileSwitch.profileName, - ValueWithUnit.Timestamp(profileSwitch.timestamp)) - disposable += repository.runTransactionForResult(InvalidateProfileSwitchTransaction(profileSwitch.id)) - .subscribe( - { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated ProfileSwitch $it") } }, - { aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it) } + rh.gs(R.string.careportal_profileswitch) + ": " + profileSwitch.profileName + + "\n" + rh.gs(R.string.date) + ": " + dateUtil.dateAndTimeString(profileSwitch.timestamp), Runnable { + uel.log( + Action.PROFILE_SWITCH_REMOVED, Sources.Treatments, profileSwitch.profileName, + ValueWithUnit.Timestamp(profileSwitch.timestamp) ) - }) + disposable += repository.runTransactionForResult(InvalidateProfileSwitchTransaction(profileSwitch.id)) + .subscribe( + { result -> result.invalidated.forEach { aapsLogger.debug(LTag.DATABASE, "Invalidated ProfileSwitch $it") } }, + { aapsLogger.error(LTag.DATABASE, "Error while invalidating ProfileSwitch", it) } + ) + }) } } binding.clone.setOnClickListener { activity?.let { activity -> val profileSwitch = (it.tag as ProfileSealed.PS).value val profileSealed = it.tag as ProfileSealed - OKDialog.showConfirmation(activity, rh.gs(R.string.careportal_profileswitch), rh.gs(R.string.copytolocalprofile) + "\n" + profileSwitch.getCustomizedName() + "\n" + dateUtil.dateAndTimeString(profileSwitch.timestamp), Runnable { - uel.log(Action.PROFILE_SWITCH_CLONED, Sources.Treatments, - profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_"), - ValueWithUnit.Timestamp(profileSwitch.timestamp), - ValueWithUnit.SimpleString(profileSwitch.profileName)) - val nonCustomized = profileSealed.convertToNonCustomizedProfile(dateUtil) - localProfilePlugin.addProfile(localProfilePlugin.copyFrom(nonCustomized, profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_"))) - rxBus.send(EventLocalProfileChanged()) - }) + OKDialog.showConfirmation( + activity, + rh.gs(R.string.careportal_profileswitch), + rh.gs(R.string.copytolocalprofile) + "\n" + profileSwitch.getCustomizedName() + "\n" + dateUtil.dateAndTimeString(profileSwitch.timestamp), + Runnable { + uel.log( + Action.PROFILE_SWITCH_CLONED, Sources.Treatments, + profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_"), + ValueWithUnit.Timestamp(profileSwitch.timestamp), + ValueWithUnit.SimpleString(profileSwitch.profileName) + ) + val nonCustomized = profileSealed.convertToNonCustomizedProfile(dateUtil) + localProfilePlugin.addProfile( + localProfilePlugin.copyFrom( + nonCustomized, + profileSwitch.getCustomizedName() + " " + dateUtil.dateAndTimeString(profileSwitch.timestamp).replace(".", "_") + ) + ) + rxBus.send(EventLocalProfileChanged()) + }) } } binding.remove.paintFlags = binding.remove.paintFlags or Paint.UNDERLINE_TEXT_FLAG diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt index 065a2f1fc3..25865c4afb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/activities/QuickWizardListActivity.kt @@ -4,6 +4,7 @@ import android.annotation.SuppressLint import android.os.Bundle import android.util.Log import android.view.LayoutInflater +import android.view.MenuItem import android.view.MotionEvent import android.view.View import android.view.ViewGroup @@ -12,26 +13,30 @@ import android.widget.ImageView import android.widget.TextView import androidx.fragment.app.FragmentManager import androidx.recyclerview.widget.ItemTouchHelper -import androidx.recyclerview.widget.ItemTouchHelper.* +import androidx.recyclerview.widget.ItemTouchHelper.ACTION_STATE_DRAG +import androidx.recyclerview.widget.ItemTouchHelper.DOWN +import androidx.recyclerview.widget.ItemTouchHelper.END +import androidx.recyclerview.widget.ItemTouchHelper.START +import androidx.recyclerview.widget.ItemTouchHelper.UP import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import info.nightscout.androidaps.R -import info.nightscout.androidaps.activities.NoSplashAppCompatActivity +import info.nightscout.androidaps.activities.DaggerAppCompatActivityWithResult import info.nightscout.androidaps.databinding.OverviewQuickwizardlistActivityBinding import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.general.overview.dialogs.EditQuickWizardDialog import info.nightscout.androidaps.plugins.general.overview.events.EventQuickWizardChange import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy -import io.reactivex.rxkotlin.plusAssign import info.nightscout.androidaps.utils.rx.AapsSchedulers import info.nightscout.androidaps.utils.wizard.QuickWizard import info.nightscout.androidaps.utils.wizard.QuickWizardEntry import info.nightscout.shared.sharedPreferences.SP import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import javax.inject.Inject -class QuickWizardListActivity : NoSplashAppCompatActivity() { +class QuickWizardListActivity : DaggerAppCompatActivityWithResult() { @Inject lateinit var aapsSchedulers: AapsSchedulers @Inject lateinit var rxBus: RxBus @@ -176,6 +181,10 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() { binding = OverviewQuickwizardlistActivityBinding.inflate(layoutInflater) setContentView(binding.root) + title = rh.gs(R.string.quickwizard) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + supportActionBar?.setDisplayShowHomeEnabled(true) + binding.recyclerview.setHasFixedSize(true) binding.recyclerview.layoutManager = LinearLayoutManager(this) binding.recyclerview.adapter = RecyclerViewAdapter(supportFragmentManager) @@ -203,4 +212,14 @@ class QuickWizardListActivity : NoSplashAppCompatActivity() { disposable.clear() super.onPause() } + + override fun onOptionsItemSelected(item: MenuItem): Boolean = + when (item.itemId) { + android.R.id.home -> { + finish() + true + } + + else -> false + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt index e7abb4690d..af5593e3ca 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/EditQuickWizardDialog.kt @@ -105,7 +105,8 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener { binding.from.setOnClickListener { context?.let { TimePickerDialog( - it, fromTimeSetListener, + it, R.style.MaterialPickerTheme, + fromTimeSetListener, T.secs(fromSeconds.toLong()).hours().toInt(), T.secs((fromSeconds % 3600).toLong()).mins().toInt(), DateFormat.is24HourFormat(context) @@ -123,7 +124,8 @@ class EditQuickWizardDialog : DaggerDialogFragment(), View.OnClickListener { binding.to.setOnClickListener { context?.let { TimePickerDialog( - it, toTimeSetListener, + it, R.style.MaterialPickerTheme, + toTimeSetListener, T.secs(toSeconds.toLong()).hours().toInt(), T.secs((toSeconds % 3600).toLong()).mins().toInt(), DateFormat.is24HourFormat(context) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt index 1fa1f3711f..78a31caa92 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/profile/local/LocalProfileFragment.kt @@ -24,11 +24,13 @@ import info.nightscout.androidaps.interfaces.Profile import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.profile.local.events.EventLocalProfileChanged -import info.nightscout.androidaps.utils.* +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.DecimalFormatter +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.HardLimits import info.nightscout.androidaps.utils.alertDialogs.OKDialog import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers -import info.nightscout.androidaps.utils.ui.SpinnerHelper import info.nightscout.androidaps.utils.ui.TimeListEdit import info.nightscout.shared.SafeParse import info.nightscout.shared.logging.AAPSLogger @@ -54,12 +56,12 @@ class LocalProfileFragment : DaggerFragment() { private var disposable: CompositeDisposable = CompositeDisposable() private var basalView: TimeListEdit? = null - private var spinner: SpinnerHelper? = null +// private var spinner: SpinnerHelper? = null private val save = Runnable { doEdit() basalView?.updateLabel(rh.gs(R.string.basal_label) + ": " + sumLabel()) - localProfilePlugin.profile?.getSpecificProfile(spinner?.selectedItem.toString())?.let { + localProfilePlugin.profile?.getSpecificProfile(binding.profileList.text.toString())?.let { binding.basalGraph.show(ProfileSealed.Pure(it)) binding.icGraph.show(ProfileSealed.Pure(it)) binding.isfGraph.show(ProfileSealed.Pure(it)) @@ -135,56 +137,118 @@ class LocalProfileFragment : DaggerFragment() { binding.name.addTextChangedListener(textWatch) binding.dia.setParams(currentProfile.dia, hardLimits.minDia(), hardLimits.maxDia(), 0.1, DecimalFormat("0.0"), false, null, textWatch) binding.dia.tag = "LP_DIA" - TimeListEdit(context, aapsLogger, dateUtil, view, R.id.ic_holder, "IC", rh.gs(R.string.ic_long_label), currentProfile.ic, null, doubleArrayOf(hardLimits.minIC(), hardLimits.maxIC()), null, 0.1, DecimalFormat ("0.0"), save) - basalView = TimeListEdit(context, aapsLogger, dateUtil, view, R.id.basal_holder, "BASAL", rh.gs(R.string.basal_long_label) + ": " + sumLabel(), currentProfile.basal, null, doubleArrayOf(pumpDescription.basalMinimumRate, pumpDescription.basalMaximumRate), null, 0.01, DecimalFormat("0.00"), save) + TimeListEdit( + context, + aapsLogger, + dateUtil, + view, + R.id.ic_holder, + "IC", + rh.gs(R.string.ic_long_label), + currentProfile.ic, + null, + doubleArrayOf(hardLimits.minIC(), hardLimits.maxIC()), + null, + 0.1, + DecimalFormat("0.0"), + save + ) + basalView = + TimeListEdit( + context, + aapsLogger, + dateUtil, + view, + R.id.basal_holder, + "BASAL", + rh.gs(R.string.basal_long_label) + ": " + sumLabel(), + currentProfile.basal, + null, + doubleArrayOf(pumpDescription.basalMinimumRate, pumpDescription.basalMaximumRate), + null, + 0.01, + DecimalFormat("0.00"), + save + ) if (units == Constants.MGDL) { val isfRange = doubleArrayOf(HardLimits.MIN_ISF, HardLimits.MAX_ISF) - TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null, isfRange , null, 1.0, DecimalFormat("0"), save) - TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target_holder, "TARGET", rh.gs(R.string.target_long_label), currentProfile.targetLow, currentProfile.targetHigh, HardLimits.VERY_HARD_LIMIT_MIN_BG, HardLimits.VERY_HARD_LIMIT_TARGET_BG, 1.0, DecimalFormat("0"), save) + TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null, isfRange, null, 1.0, DecimalFormat("0"), save) + TimeListEdit( + context, + aapsLogger, + dateUtil, + view, + R.id.target_holder, + "TARGET", + rh.gs(R.string.target_long_label), + currentProfile.targetLow, + currentProfile.targetHigh, + HardLimits.VERY_HARD_LIMIT_MIN_BG, + HardLimits.VERY_HARD_LIMIT_TARGET_BG, + 1.0, + DecimalFormat("0"), + save + ) } else { - val isfRange = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.MIN_ISF, GlucoseUnit.MMOL)), - roundDown(Profile.fromMgdlToUnits(HardLimits.MAX_ISF, GlucoseUnit.MMOL))) - TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null,isfRange , null, 0.1, DecimalFormat("0.0"), save) - val range1 = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[0], GlucoseUnit.MMOL)), - roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[1], GlucoseUnit.MMOL))) - val range2 = doubleArrayOf(roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[0], GlucoseUnit.MMOL)), - roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[1], GlucoseUnit.MMOL))) - Log.i("TimeListEdit", "build: range1" + range1[0] + " " + range1[1] + " range2" + range2[0] + " " + range2[1]) - TimeListEdit(context, aapsLogger, dateUtil, view, R.id.target_holder, "TARGET", rh.gs(R.string.target_long_label), currentProfile.targetLow, currentProfile.targetHigh, range1 , range2, 0.1, DecimalFormat("0.0"), save) + val isfRange = doubleArrayOf( + roundUp(Profile.fromMgdlToUnits(HardLimits.MIN_ISF, GlucoseUnit.MMOL)), + roundDown(Profile.fromMgdlToUnits(HardLimits.MAX_ISF, GlucoseUnit.MMOL)) + ) + TimeListEdit(context, aapsLogger, dateUtil, view, R.id.isf_holder, "ISF", rh.gs(R.string.isf_long_label), currentProfile.isf, null, isfRange, null, 0.1, DecimalFormat("0.0"), save) + val range1 = doubleArrayOf( + roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[0], GlucoseUnit.MMOL)), + roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MIN_BG[1], GlucoseUnit.MMOL)) + ) + val range2 = doubleArrayOf( + roundUp(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[0], GlucoseUnit.MMOL)), + roundDown(Profile.fromMgdlToUnits(HardLimits.VERY_HARD_LIMIT_MAX_BG[1], GlucoseUnit.MMOL)) + ) + Log.i("TimeListEdit", "build: range1" + range1[0] + " " + range1[1] + " range2" + range2[0] + " " + range2[1]) + TimeListEdit( + context, + aapsLogger, + dateUtil, + view, + R.id.target_holder, + "TARGET", + rh.gs(R.string.target_long_label), + currentProfile.targetLow, + currentProfile.targetHigh, + range1, + range2, + 0.1, + DecimalFormat("0.0"), + save + ) } // Spinner - spinner = SpinnerHelper(binding.spinner) context?.let { context -> val profileList: ArrayList = localProfilePlugin.profile?.getProfileList() ?: ArrayList() - spinner?.adapter = ArrayAdapter(context, R.layout.spinner_centered, profileList) - val selection = localProfilePlugin.currentProfileIndex - if (selection in 0 until profileList.size) spinner?.setSelection(selection) + binding.profileList.setAdapter(ArrayAdapter(context, R.layout.spinner_centered, profileList)) } ?: return - spinner?.setOnItemSelectedListener(object : AdapterView.OnItemSelectedListener { - override fun onNothingSelected(parent: AdapterView<*>?) { - } - override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - if (localProfilePlugin.isEdited) { - activity?.let { activity -> - OKDialog.showConfirmation(activity, rh.gs(R.string.doyouwantswitchprofile), { + binding.profileList.onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> + if (localProfilePlugin.isEdited) { + activity?.let { activity -> + OKDialog.showConfirmation( + activity, rh.gs(R.string.doyouwantswitchprofile), + { localProfilePlugin.currentProfileIndex = position localProfilePlugin.isEdited = false build() }, { val selection = localProfilePlugin.currentProfileIndex - if (selection in 0 until (spinner?.adapter?.count ?: -1)) spinner?.setSelection(selection) - } - ) - } - } else { - localProfilePlugin.currentProfileIndex = position - build() + if (selection in 0 until (binding.profileList.adapter?.count ?: -1)) binding.profileList.setSelection(selection) + } + ) } + } else { + localProfilePlugin.currentProfileIndex = position + build() } - }) - localProfilePlugin.profile?.getSpecificProfile(spinner?.selectedItem.toString())?.let { + } + localProfilePlugin.profile?.getSpecificProfile(binding.profileList.text.toString())?.let { binding.basalGraph.show(ProfileSealed.Pure(it)) binding.icGraph.show(ProfileSealed.Pure(it)) binding.isfGraph.show(ProfileSealed.Pure(it)) @@ -206,8 +270,12 @@ class LocalProfileFragment : DaggerFragment() { if (localProfilePlugin.isEdited) { activity?.let { OKDialog.show(it, "", rh.gs(R.string.saveorresetchangesfirst)) } } else { - uel.log(Action.CLONE_PROFILE, Sources.LocalProfile, ValueWithUnit.SimpleString(localProfilePlugin.currentProfile()?.name - ?: "")) + uel.log( + Action.CLONE_PROFILE, Sources.LocalProfile, ValueWithUnit.SimpleString( + localProfilePlugin.currentProfile()?.name + ?: "" + ) + ) localProfilePlugin.cloneProfile() build() } @@ -216,8 +284,12 @@ class LocalProfileFragment : DaggerFragment() { binding.profileRemove.setOnClickListener { activity?.let { activity -> OKDialog.showConfirmation(activity, rh.gs(R.string.deletecurrentprofile), { - uel.log(Action.PROFILE_REMOVED, Sources.LocalProfile, ValueWithUnit.SimpleString(localProfilePlugin.currentProfile()?.name - ?: "")) + uel.log( + Action.PROFILE_REMOVED, Sources.LocalProfile, ValueWithUnit.SimpleString( + localProfilePlugin.currentProfile()?.name + ?: "" + ) + ) localProfilePlugin.removeCurrentProfile() build() }, null) @@ -245,8 +317,12 @@ class LocalProfileFragment : DaggerFragment() { if (!localProfilePlugin.isValidEditState(activity)) { return@setOnClickListener //Should not happen as saveButton should not be visible if not valid } - uel.log(Action.STORE_PROFILE, Sources.LocalProfile, ValueWithUnit.SimpleString(localProfilePlugin.currentProfile()?.name - ?: "")) + uel.log( + Action.STORE_PROFILE, Sources.LocalProfile, ValueWithUnit.SimpleString( + localProfilePlugin.currentProfile()?.name + ?: "" + ) + ) localProfilePlugin.storeSettings(activity) build() } @@ -294,7 +370,7 @@ class LocalProfileFragment : DaggerFragment() { val isEdited = localProfilePlugin.isEdited if (isValid) { this.view?.setBackgroundColor(rh.gc(R.color.ok_background)) - binding.spinner.isEnabled = true + binding.profileList.isEnabled = true if (isEdited) { //edited profile -> save first @@ -306,7 +382,7 @@ class LocalProfileFragment : DaggerFragment() { } } else { this.view?.setBackgroundColor(rh.gc(R.color.error_background)) - binding.spinner.isEnabled = false + binding.profileList.isEnabled = false binding.profileswitch.visibility = View.GONE binding.save.visibility = View.GONE //don't save an invalid profile } diff --git a/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/PrefImportSummaryDialog.kt b/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/PrefImportSummaryDialog.kt index b51e5960e6..46756397d5 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/PrefImportSummaryDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/PrefImportSummaryDialog.kt @@ -28,7 +28,7 @@ object PrefImportSummaryDialog { @SuppressLint("InflateParams") fun showSummary(context: Context, importOk: Boolean, importPossible: Boolean, prefs: Prefs, ok: (() -> Unit)?, cancel: (() -> Unit)? = null) { - @StyleRes val theme: Int = if (importOk) R.style.AppTheme else { + @StyleRes val theme: Int = if (importOk) R.style.DialogTheme else { if (importPossible) R.style.AppThemeWarningDialog else R.style.AppThemeErrorDialog } @@ -92,7 +92,7 @@ object PrefImportSummaryDialog { webView.setBackgroundColor(Color.TRANSPARENT) webView.setLayerType(WebView.LAYER_TYPE_SOFTWARE, null) - AlertDialogHelper.Builder(context, R.style.AppTheme) + AlertDialogHelper.Builder(context, R.style.DialogTheme) .setCustomTitle( AlertDialogHelper.buildCustomTitle( context, diff --git a/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/TwoMessagesAlertDialog.kt b/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/TwoMessagesAlertDialog.kt index a2c4e78e2f..0bfd1f72f9 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/TwoMessagesAlertDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/alertDialogs/TwoMessagesAlertDialog.kt @@ -19,7 +19,7 @@ object TwoMessagesAlertDialog { val secondMessageLayout = LayoutInflater.from(context).inflate(R.layout.dialog_alert_two_messages, null) (secondMessageLayout.findViewById(R.id.password_prompt_title) as TextView).text = secondMessage - val dialog = AlertDialogHelper.Builder(context) + AlertDialogHelper.Builder(context, R.style.DialogTheme) .setMessage(message) .setCustomTitle( AlertDialogHelper.buildCustomTitle( @@ -40,7 +40,7 @@ object TwoMessagesAlertDialog { if (cancel != null) runOnUiThread { cancel() } } .show() - dialog.setCanceledOnTouchOutside(false) + .setCanceledOnTouchOutside(false) } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_local_activate.xml b/app/src/main/res/drawable/ic_local_activate.xml index 905ade57d3..b6ef8ff973 100644 --- a/app/src/main/res/drawable/ic_local_activate.xml +++ b/app/src/main/res/drawable/ic_local_activate.xml @@ -5,8 +5,8 @@ android:viewportHeight="24"> + android:fillColor="@color/ic_local_activate"/> + android:fillColor="@color/ic_local_activate"/> diff --git a/app/src/main/res/drawable/ic_local_reset.xml b/app/src/main/res/drawable/ic_local_reset.xml index 07faa6ee4d..b1008a92da 100644 --- a/app/src/main/res/drawable/ic_local_reset.xml +++ b/app/src/main/res/drawable/ic_local_reset.xml @@ -5,5 +5,5 @@ android:viewportHeight="24"> + android:fillColor="@color/ic_local_reset"/> diff --git a/app/src/main/res/layout/actions_fragment.xml b/app/src/main/res/layout/actions_fragment.xml index 7d43edb857..9e2810b77b 100644 --- a/app/src/main/res/layout/actions_fragment.xml +++ b/app/src/main/res/layout/actions_fragment.xml @@ -27,14 +27,14 @@ -