From ef6ee43c326c96ab97cc800a9128e7e530eb86bd Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sat, 2 Jun 2018 18:06:04 +0200 Subject: [PATCH 01/44] One-short guards for Fill/Prime dialog. --- .../plugins/Actions/dialogs/FillDialog.java | 69 ++++++++++++------- 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java index 7b9b8570d6..558a7c381c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/dialogs/FillDialog.java @@ -61,6 +61,10 @@ public class FillDialog extends DialogFragment implements OnClickListener { private EditText notesEdit; + //one shot guards + private boolean accepted; + private boolean okClicked; + final private TextWatcher textWatcher = new TextWatcher() { @Override public void afterTextChanged(Editable s) { @@ -163,7 +167,14 @@ public class FillDialog extends DialogFragment implements OnClickListener { } - private void confirmAndDeliver() { + private synchronized void confirmAndDeliver() { + if (okClicked) { + log.debug("guarding: ok already clicked"); + dismiss(); + return; + } + okClicked = true; + try { Double insulin = SafeParse.stringToDouble(editInsulin.getText()); @@ -198,32 +209,40 @@ public class FillDialog extends DialogFragment implements OnClickListener { if (insulinAfterConstraints > 0 || pumpSiteChangeCheckbox.isChecked() || insulinCartridgeChangeCheckbox.isChecked()) { builder.setMessage(Html.fromHtml(Joiner.on("
").join(confirmMessage))); builder.setPositiveButton(MainApp.gs(R.string.primefill), (dialog, id) -> { - if (finalInsulinAfterConstraints > 0) { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.insulin = finalInsulinAfterConstraints; - detailedBolusInfo.context = context; - detailedBolusInfo.source = Source.USER; - detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history) - detailedBolusInfo.notes = notes; - ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { - @Override - public void run() { - if (!result.success) { - Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); - i.putExtra("soundid", R.raw.boluserror); - i.putExtra("status", result.comment); - i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); + synchronized (builder) { + if (accepted) { + log.debug("guarding: already accepted"); + return; + } + accepted = true; + + if (finalInsulinAfterConstraints > 0) { + DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); + detailedBolusInfo.insulin = finalInsulinAfterConstraints; + detailedBolusInfo.context = context; + detailedBolusInfo.source = Source.USER; + detailedBolusInfo.isValid = false; // do not count it in IOB (for pump history) + detailedBolusInfo.notes = notes; + ConfigBuilderPlugin.getCommandQueue().bolus(detailedBolusInfo, new Callback() { + @Override + public void run() { + if (!result.success) { + Intent i = new Intent(MainApp.instance(), ErrorHelperActivity.class); + i.putExtra("soundid", R.raw.boluserror); + i.putExtra("status", result.comment); + i.putExtra("title", MainApp.gs(R.string.treatmentdeliveryerror)); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); + } } - } - }); - FabricPrivacy.getInstance().logCustom(new CustomEvent("Fill")); + }); + FabricPrivacy.getInstance().logCustom(new CustomEvent("Fill")); + } + if (pumpSiteChangeCheckbox.isChecked()) + NSUpload.uploadEvent(CareportalEvent.SITECHANGE, now(), notes); + if (insulinCartridgeChangeCheckbox.isChecked()) + NSUpload.uploadEvent(CareportalEvent.INSULINCHANGE, now() + 1000, notes); } - if (pumpSiteChangeCheckbox.isChecked()) - NSUpload.uploadEvent(CareportalEvent.SITECHANGE, now(), notes); - if (insulinCartridgeChangeCheckbox.isChecked()) - NSUpload.uploadEvent(CareportalEvent.INSULINCHANGE, now() + 1000, notes); }); } else { builder.setMessage(MainApp.gs(R.string.no_action_selected)); From d31b90cd3e4cbd1341f482882fa798afc7d2b0d5 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Mon, 4 Jun 2018 15:38:06 +0200 Subject: [PATCH 02/44] Fix format specifier in French translation. --- app/src/main/res/values-fr/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index f9b4bb1ac4..2bfca7cec0 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -468,7 +468,7 @@ Glimp Le dispositif n’apparaît pas pour renforcer la liste blanche de l’optimisation de batterie! Autorisez l\'accès svp - % a besoin de la liste blanche de l’optimisation batterie pour une bonne performance + %s a besoin de la liste blanche de l\’optimisation batterie pour une bonne performance Loop suspendu Suspendu (%d m) Superbolus (%d m) From 536fe3e5d2bff5a76b80aa2ffa88da17da669f18 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Tue, 5 Jun 2018 00:15:41 +0200 Subject: [PATCH 03/44] higher contrast ok and cancel buttons --- app/src/main/res/values/colors.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index d36a1384a0..eee51c703a 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -35,7 +35,8 @@ #212121 #000000 - #009688 + #40bbaa + #40bbaa #00695c #121212 From 32f4a08fa65786229c7884154eb95451fc0f8de9 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Tue, 5 Jun 2018 13:24:48 +0200 Subject: [PATCH 04/44] slightly more padding on top buttons/fields --- app/src/main/res/layout/overview_fragment.xml | 7 +++++++ app/src/main/res/layout/overview_fragment_nsclient.xml | 9 ++++++++- .../res/layout/overview_fragment_nsclient_tablet.xml | 7 +++++++ .../main/res/layout/overview_fragment_smallheight.xml | 9 ++++++++- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/overview_fragment.xml b/app/src/main/res/layout/overview_fragment.xml index db1ad49b69..c9fa19c38c 100644 --- a/app/src/main/res/layout/overview_fragment.xml +++ b/app/src/main/res/layout/overview_fragment.xml @@ -41,7 +41,10 @@ android:layout_marginRight="5dp" android:layout_weight="1" android:gravity="center_vertical|center_horizontal" + android:paddingBottom="3dp" + android:paddingTop="3dp" android:text="Open Loop" + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -53,6 +56,8 @@ android:layout_marginRight="5dp" android:layout_weight="1" android:gravity="center_vertical|center_horizontal" + android:paddingBottom="3dp" + android:paddingTop="3dp" android:text="Profile" android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -64,6 +69,8 @@ android:layout_weight="1" android:gravity="center_vertical|center_horizontal" android:text="TempTarget" + android:paddingBottom="3dp" + android:paddingTop="3dp" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="@color/mdtp_white" /> diff --git a/app/src/main/res/layout/overview_fragment_nsclient.xml b/app/src/main/res/layout/overview_fragment_nsclient.xml index bc66f0a407..3b9d51ff19 100644 --- a/app/src/main/res/layout/overview_fragment_nsclient.xml +++ b/app/src/main/res/layout/overview_fragment_nsclient.xml @@ -24,7 +24,7 @@ @@ -35,7 +35,10 @@ android:layout_marginRight="5dp" android:layout_weight="1" android:gravity="center_vertical|center_horizontal" + android:paddingBottom="3dp" + android:paddingTop="3dp" android:text="Open Loop" + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -47,6 +50,8 @@ android:layout_marginRight="5dp" android:layout_weight="1" android:gravity="center_vertical|center_horizontal" + android:paddingBottom="3dp" + android:paddingTop="3dp" android:text="Profile" android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -58,6 +63,8 @@ android:layout_weight="1" android:gravity="center_vertical|center_horizontal" android:text="TempTarget" + android:paddingBottom="3dp" + android:paddingTop="3dp" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="@color/mdtp_white" /> diff --git a/app/src/main/res/layout/overview_fragment_nsclient_tablet.xml b/app/src/main/res/layout/overview_fragment_nsclient_tablet.xml index a81a514bf0..f9826cb211 100644 --- a/app/src/main/res/layout/overview_fragment_nsclient_tablet.xml +++ b/app/src/main/res/layout/overview_fragment_nsclient_tablet.xml @@ -41,7 +41,10 @@ android:layout_marginRight="5dp" android:layout_weight="1" android:gravity="center_vertical|center_horizontal" + android:paddingBottom="3dp" + android:paddingTop="3dp" android:text="Open Loop" + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -53,6 +56,8 @@ android:layout_marginRight="5dp" android:layout_weight="1" android:gravity="center_vertical|center_horizontal" + android:paddingBottom="3dp" + android:paddingTop="3dp" android:text="Profile" android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -64,6 +69,8 @@ android:layout_weight="1" android:gravity="center_vertical|center_horizontal" android:text="TempTarget" + android:paddingBottom="3dp" + android:paddingTop="3dp" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="@color/mdtp_white" /> diff --git a/app/src/main/res/layout/overview_fragment_smallheight.xml b/app/src/main/res/layout/overview_fragment_smallheight.xml index 5d1e78c5db..498cb6cc80 100644 --- a/app/src/main/res/layout/overview_fragment_smallheight.xml +++ b/app/src/main/res/layout/overview_fragment_smallheight.xml @@ -24,7 +24,7 @@ @@ -35,7 +35,10 @@ android:layout_marginRight="5dp" android:layout_weight="1" android:gravity="center_vertical|center_horizontal" + android:paddingBottom="3dp" + android:paddingTop="3dp" android:text="Open Loop" + android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -47,6 +50,8 @@ android:layout_marginRight="5dp" android:layout_weight="1" android:gravity="center_vertical|center_horizontal" + android:paddingBottom="3dp" + android:paddingTop="3dp" android:text="Profile" android:textAppearance="?android:attr/textAppearanceSmall" /> @@ -58,6 +63,8 @@ android:layout_weight="1" android:gravity="center_vertical|center_horizontal" android:text="TempTarget" + android:paddingBottom="3dp" + android:paddingTop="3dp" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="@color/mdtp_white" /> From 5df51e8a6ead630646294e818557433ccfe510b7 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 5 Jun 2018 14:35:18 +0200 Subject: [PATCH 05/44] check for NPE --- .../androidaps/plugins/Overview/Dialogs/WizardDialog.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java index c38f41b825..36b777733a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java @@ -408,9 +408,9 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com private void initDialog() { Profile profile = MainApp.getConfigBuilder().getProfile(); - ProfileStore profileStore = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile(); + ProfileStore profileStore = MainApp.getConfigBuilder().getActiveProfileInterface() != null ? MainApp.getConfigBuilder().getActiveProfileInterface().getProfile() : null; - if (profile == null) { + if (profile == null || profileStore == null) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.noprofile)); dismiss(); return; From 65c8cb22ef54ae9428c849079b22546115dde49b Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 5 Jun 2018 14:38:00 +0200 Subject: [PATCH 06/44] check for null context --- .../androidaps/plugins/Overview/OverviewFragment.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java index 31aa098579..fadb30420c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java @@ -672,12 +672,15 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, private void onClickAcceptTemp() { Profile profile = MainApp.getConfigBuilder().getProfile(); + Context context = getContext(); + + if (context == null) return; if (LoopPlugin.getPlugin().isEnabled(PluginType.LOOP) && profile != null) { LoopPlugin.getPlugin().invoke("Accept temp button", false); final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun; if (finalLastRun != null && finalLastRun.lastAPSRun != null && finalLastRun.constraintsProcessed.isChangeRequested()) { - AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(MainApp.gs(R.string.confirmation)); builder.setMessage(MainApp.gs(R.string.setbasalquestion) + "\n" + finalLastRun.constraintsProcessed); builder.setPositiveButton(MainApp.gs(R.string.ok), (dialog, id) -> { From 0996b0f1825baa95774de3c5c34be7111170a3fb Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Wed, 6 Jun 2018 22:09:40 +0200 Subject: [PATCH 07/44] Ro update --- app/src/main/res/values-ro/strings.xml | 488 ++++++++++++++++++++++++- 1 file changed, 486 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 1eb065e0d6..62cbed5d87 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -40,11 +40,11 @@ Cantitatea de insulină Cantitatea de carbohidrați BG - Carbohidrați + Carbo Corecție U Bolus IOB - Fă acum + Execută POMPĂ VIRTUALĂ Bolus extins OK @@ -495,4 +495,488 @@ Toate trimiterile de date către NS sunt oprite. AAPS este conectat la NS dar nu se fac schimbări în NS Pas bazală Pas bolus + TT + Rată bazală normală + Bazală temporală + Baterie + Rezervor + Rezultat + BazalăTemp + BazalăTemp setată în pompă + Ultima comandă + OK + Renunță + NU AȚI SELECTAT APS SAU NU EXISTĂ REZULTAT + Siguranță + Modul inactiv + Încălcare a unei limite + Eroare la livrarea bolusului + Eroare la setare bazală temporară + Valoare bazală [%] + % (100% = curent) + Acceptă noua bazală temporară: + Tratament + Calculator + Limitare aplicată! + Confirmare + Introduceți tratament nou: + Bolus + Bolus: + Bazală + Bazală: + Carbo + Schimbați valoarea! + Setați un nou bolus extins: + Sursă glicemie + xDrip + Mod APS + Buclă închisă + Buclă deschisă + Versiune de Nightscout nesuportată + Română + Ultimul bolus + Bolus oprit + Se oprește bolusul + Se activează opțiuni pentru uzul în timpul zilei, cum ar fi SMB + Trebuie sa citiți wiki și măriți maxIOB pentru a obține SMB corect! Un start bun este maxIOB=media bolusurilor + 3x maxima bazalei din zi + %.2f este limitată la %.2f + Valarea %s este mai mare decât limita fizică + Sincronizează cu NS + Hipo + Autosens ajustează țintele la + Adult rezistent la insulină + DanaRv2 + Fiasp + Ultima conexiune + BolusExtins + ȚintăTemporară + Renunță la bolusul extins + Vechime senzor + Vechime canulă + Vechime insulină + ore + Tip bazală + Profil invalid!!! + SchimbareProfil + Vechime baterie pompă + Schimbare baterie pompă + Opțiuni alarmare + Hiper urgent + Hiper + Hipo + Hipo urgent + Date învechite + Date mult prea vechi + Prag vechime date [min] + Prag date mult prea vechi [min] + Interval pentru autosens [o] + Numărul de ore din trecut pentru detectarea sensibilității (se exclude timpul de absorbție al carbo) + Pompă + OpenAPS + Uploader + Detectare sensilitate + SENS + Sensibilitate Oref0 + Sensibilitate AAPS + Setări absorbție + Timp maxim absorbție masă [o] + Timp în ore la care se presupune că toți carbo sunt absorbiți + VS + VI + VC + BAT + OAPS + UPLD + BAZ + EXT + Ecran blocare + Blocat + Trebuie introduși toți carbo la pornirea Autosens. În caz contrar, acțiunea carbo va fi percepută ca schimbare a sensibilității! + Mediană sensibilitate + OK + Renunță + Nu s-au încărcat toate profilele! + Nu s-au salvat valorile! + Permite anunțarea altor aplicații (ca xDrip). + Permite anunțuri locale. + ACTIVITATE ȘÎ VERIFICĂRI + CARBO ȘÎ BOLUS + CGM ȘÎ OPENAPS + POMPĂ + Valoare bazală [U/o] + Durată [min] + OpenAPS SMB + SMB + Activează UAM + Activează SMB + Folosește SMB în locul bazalei temporare pentru reacție mai rapidă + S-a detectat masă neanunțată + Curbă timp vârf IOB + Timp vârf [min] + Oref Fără-Vârf + Oref Insulină-Rapidă + Oref Insulină-UltraRapidă + Insulină personalizată + DIA din %f prea scurtă - se folosește %f în schimb! + Activează profil + Data + INVALID + Se așteaptă conectarea la pompă + Conectare OK + Conectare nereușită + CONECTARE + Niciun dispozitiv găsit până acum + Rezervor gol + Alertă măsurare glicemie + Nivel insulină rămas + DanaRS + Dana + Pompa selectată + Conectare la pompă nouă + Viteză bolusare + Setare pas bazală la 0.01 U/o + Număr serial + Procentaj + Decalare + Ținte-Temporare implicite + durată semănâncăcurând + țintă semănâncăcurând + durată activitate + țintă activitate + durată țintă + țintă hipo + Amorsare tub + Se obține starea bolusului extins + Se obține starea bolusului + Se obține starea bazalei temporare + Se obțin setările pompei + Se obține ora pompei + refolosire + Controlare din ceas + Setare Ținte-Temporare și se introduc Tratamente din ceas. + Conectare eșuată + Mâncare + g + m + o + ]]> + kJ + En + Pr + Grăsime + ]]> + Se așteaptă finalul bolusării. Mai sunt %d sec. + Se procesează activitatea + Pornire livrare bolus + Se execută comanda chiar acum + S-a corectat driverul pompei + Pompă indisponibilă + Lipsesc date glicemie + Se folosesc notificările sistemului pentru alerte și notificări + Alerte locale + Alarmează dacă nu se primesc glicemii + Se alertează dacă pompa este indisponibilă + Prag pompă indisponibilă [min] + Alarmă urgentă + INFO + Bluetooth + BT Watchdog + Oprește bluetooth-ul telefonului pentru o secundă dacă nu se poate conecta la pompă. Aceasta poate ajuta în cazul telefoanelor cu bluetooth incompatitibil. + App DexcomG5 (cu patch) + Încarcă date glicemie în NS + Setări înregistrare G5 + Arată variație detaliată + Arată variație cu încă o zecimală + Max minute de bazală la care să se limiteze SMB + Soft pompă incompatibil + Trimite date glicemie la xDrip+ + Selectați 640g/Eversense ca sursă de date în xDrip+ + Glicemie NSClient + Valoare bazală înlocuită cu valoarea minimă suportată + Calcul glicemie + Calcul IOB bolus + Calcul IOB bazală + Calcul pantă + Calcul superbolus + Da + Nu + Doar pozitiv + Doar negativ + Calcul COB + Calcul țintă temporară + Buclă activată + APS selectat + NSClient are drepturi de scriere + Mod buclă închisă activat + IOB maxim configurat corect + Glicemie disponibilă din sursa selectată + Valori bazale nealiniate la ore: %s + Profil invalid + Se programează pompa pentru livrare bolus + Reîncarcă + Stare + Activitate + Fără conexiune de %d min + %d%% (%d min rămase) + Inițializare + Suspendat din cauza unei erori + Suspendat de utilizator + Funcționează + Se oprește TBR + Se setează TBR (%d%% / %d min) + Bolusare (%.1f U) + Reîncărcare + Operațiunea nu este suportată de pompă + Folosire nesigură: un bolus extins sau multiwave este activ. Modul buclă este setat să funcționeze în low-suspend pentru 6 ore. Doar bolusurile normale sunt posibile. + Folosire nesigură: pompa folosește un alt profil decât primul. Bucla a fost dezactivată. Selectați primul profil din pompă șî reîncercați. + Un bolus de aceeași valoare a fost livrat în ultimile două minute. Pentru a preveni bolusarea accidentală dublă și pentru a evita greșelile , acesta nu se va livra + Acum + Se citește istoricul din pompă + Se setează profilul bazalei + Nivelul insulinei din pompă este scăzut + Nivelul bateriei pompei este scăzut + Pompa are eroarea: E%d: %s + Scăzut + Gol + Normal + Ceasul pompei trebuie ajustat + Atenție + Alerta RBT ANULATĂ a fost confirmată + Pompa nu poate fi contactată. Nu s-a livrat niciun bolus + Livrare eșuată. Se pare că nu a fost livrat bolusul. Pentru siguranță, verificați în pompă pentru a evita bolusarea dublă. Pentru evitarea greșelilor, bolusurile nu sunt retrimise automat. + Doar %.2f U din totalul cerut de %.2f U a fost livrat din cauza unei erori. Verificați pompa pentru confirmare și acționați corespunzător. + Livrarea bolusului și verificarea istoricului pompei a eșuat, verificați pompa și creați manual un bolus folosind Careportal, dacă a fost livrat un bolus. + Revenire după pierderea conexiunii + Nu este suficientă insulină în rezervor + Eroare de livrare a bolusului extins + Insight + Pompă Insight + Stare + Schimbat + POMPĂ OPRITĂ + Stare actualizată + în trecut + cu + RBT activ + min. rămase + Jurnal + Ultima acțiune efectuată + min. + rămase peste + total cu + față de + Rămâneți conectat permanent + Se folosesc anulări de RBT + Anulare reală a unei RBT (generează alarmă a pompei) în loc de a seta 90% pentru 1 minut + LIBER + SINCRONIZARE + OCUPAT + SINCRONIZAT + PORNIRE + nevoi + Aplicația nu este conectată! + Aplicația pare să nu fie instalată! + Aplicație incompatibila, este necesară versiunea + Necunoscut + Se așteaptă confirmarea codului + Cod respins + Conectare aplicație + Neautorizat + Incompatibil + secundă + minut + oră + z + săptămână + e + %ds expiră %s + Stare de menținere + Statistici + Conectare preventivă + Conectare automată atunci când AndroidAPS este afișat pe ecran, înaintea cererii de efectuare a unei comenzi către pompă, pentru reducerea întârzierilor + Nerecomandat datorită epuizării bateriei + Activează SMB întotdeauna + Activează SMB întotdeauna independent de bolusuri. Este posibil doar în cazul unei surse de glicemii filtrate, cum ar fi G5 + Activează SMB după carbo + Activează SMB pentru 6 ore după carbo, chiar și cu 0 COB. Este posibil doar cu o sursă de glicemii filtrate, ca datele din G5 + Activează SMB cu COB + Activează SMB atunci când sunt COB activi. + Activează SMB cu ținte temporare + Activează SMB chiar atunci când este o țintă temporară activă (mâncare in curând, exerciții fizice) + Activează SMB cu ținte temporare mari + Activează SMB atunci când există o țintă temporară mare activă (exerciții fizice) + Lasă să funcționeze bazala temporară + Liniște + Insulină + Carbohidrați + Butoane + Trimite calibrarea către xDrip+ sau deschide calibrarea pentru G5 + Deschide xDrip+, butonul de înapoi returnează la AAPS + Cantitate de carbohidrați de adăugat când se apasă butonul + Cantitatea de insulină de adăugat când se apasă butonul + Nu s-a putut deschide aplicația CGM. Asigurați-vă că este instalată. + CGM + Vizualizare istoric + Notifică despre SMB + Arată SMB pe ceas ca și un bolus standard. + Crează anunțuri pentru erori + Crează anunțuri în Nightscout pentru dialoguri de erori și alerte locale (vizibile și în Careportal - Tratamente) + Arată previziunile pe ceas. + Predicții + Alegeri date + Încărcare \"fabric\" + Permite trimiterea de rapoarte automate de eroare și de date despre folosire către dezvoltatori prin serviciul fabric.io + Actualizați aplicația G5 la o versiune suportată + Start TT activitate + Start TT mănânc în curând + TT + Nu bolusa, doar înregistrează + Categorie + Subcategorie + Bolusul se va înregistra doar + Autocompletează valorile glicemiei lipsă din NS + SMB setat de pompă + Sensibilitate + Deviații + Carbohidrați activi + Insulină activă + Bazale + Nicio acțiune selectată, nu se va întâmpla nimic + Start TT hipo + Se folosește versiunea dev. Bucla închisă este dezactivată. + Mod inginer activat + Modul inginer nu este activat și nu este în versiunea lansată + %.2f U/h + Se citește profilul bazal + Istoricul pompei s-a schimbat după calcularea bolusului. Bolusul nu a fost livrat. Recalculați dacă mai este necesar un bolus. Dacă aceeași cantitate de bolus este necesară, așteptați două minute deoarece două bolusuri cu aceeași valoare nu sunt permise într-un interval mai mic de două minute, din rațiuni de siguranță (indiferent dacă au fost livrate sau nu). + Bolus livrat, dar nu s-a reușit înregistrarea evenimentului. Aceasta se poate întâmpla când două bolusuri mici de aceeași valoare sunt livrate în mai puțin de două minute. Verificați istoricul pompei și înregistrările tratamentelor și folosiți Careportal pentru adăugarea intrărilor lipsă. Asigurați-vă că nu adăugați intrări duble. + Se respinge temporara mare deoarece calculul nu a luat în calcul istoricul recent schimbat din pompă + Actualizare stare pompă + Rata bazală din pompă s-a schimbat și va fi actualizată în curând + Rata bazală schimbată în pompă, dar nu s-a putut actualiza + Se verifică schimbările în istoric + Mai multe bolusuri de aceeași valoare au fost importate. Doar o singură înregistrare va fi adăugată în tratamente. Verifcați manual în pompă și adăugați înregistrările folosind Careportal. Asigurați-vă că veți crea un bolus care nu se suprapune peste altul în timp. + Atenționare W31: Rezervor aproape gol + Atenționare W32: Baterie aproape terminată + Atenționare W33: Timp/dată invalide + Atenționare W34: Sfârșitul garanției + Atenționare W36: RBT terminat + Atenționare W38: Bolus anulat + Atenționare W39: Alertă timp închiriere + Mentenanță M20: Rezervorul nu este inserat + Mentenanță M21: Rezervol gol + Mentenanță M22: Baterie goală + Mentenanță M23: Oprire automată + Mentenanță M24: Ocluzie + Mentenanță M25: Închiriere terminată - sfârșitul operațiunilor + Mentenanță M26: Rezervorul nu a fost schimbat + Mentenanță M27: Descărcarea datelor eșuată + Mentenanță M28: Modul pauză expirat + Mentenanță M29: Tipul bateriei nu este setat + Mentenanță M30: Tipul rezervorului nu este setat + Eroare E6: Eroare mecanică + Eroare E7: Eroare electronică + Eroare E10: Eroare de revenire tijă piston + Eroare E13: Eroare de limbaj + Folosește doar conexiune WiFi + CGM + Obiectivul %d nu este pornit + Obiectivul %d nu este atins + Pompa nu suportă bazale temporare + Nu s-a citit o rată bazală validă din pompă + Modul buclă închisă dezactivat în preferințe + Autosens dezactivat în preferințe + SMB dezactivat în preferințe + Se limitează maximul ratei bazale la %.2f U/o datorită %s + limită pompă + trebuie să fie o valoare pozitivă + maximul multiplicatorului bazalei + maximul zilnic al multiplicatorului bazalei + S-a livrat un bolus în ultimile 3 minute, nu se livrează SMB + Bazala setată corect + Se limitează procentul ratei maxime la %d%% datorită %s + Se limitează bolusul la %.1f U datorită %s + Se limitează max IOB la %.1f U datorită %s + Se limitează carbohidrații %d g datorită %s + Se limitează IOB la %.1f U datorită %s + valoare maximă în preferințe + folosire nesigură + Citire eșuată a stării + Înregistrare schimbare a locului pompei + Înregistrare schimbare rezervor insulină + SMB dezactivat întotdeauna și după carbo deoarece sursa glicemiei nu suportă filtrare avansată + SMB nu este permis în mod buclă deschisă + Mâncare + Se așteaptă sincronizarea (%d s) + Deconectat (%d min) + Evenimente Careportal automate + Încărcare automată a schimbărilor de insulină, rezervor, baterie și alarme de pompă în Nightscout + Maximul total IOB peste care OpenAPS nu poate trece [U] + Pompă oprită + Pompă pornită + Pompă în pauză + Timpul maxim de absorbție a mesei [o] + Timpul în care orice mâncare se consideră absorbită. Carbohidrații rămași vor fi ignorați. + Timp + reset + Această valoare este denumită Max IOB în contextul OpenAPS, OpenAPS nu va adăuga mai multă insulină dacă IOB este mai mare ca această valoare + Solicitat: %.2fU Livrat: %.2fU Cod eroare: %d + Primul increment de insulină + Al doilea increment de insulină + Al treilea increment de insulină + Primul increment de carbohidrați + Al doilea increment de carbohidrați + Al treilea increment de carbohidrați + SSID WiFi + SSIDuri permise (separare prin punct și virgulă) + Ultimul bolus este mai vechi de 24 ore sau este în viitor. Verificați ca data să fie configurată corect în pompă. + Ora/data bolusului livrat de pompă pare eronat, IOB este probabil incorect. Verificați ora/data pompei. + Lipsă SchimbareProfil. Efectuați o schimbare de profil sau apăsați \"Activare profil\" în ProfilulLocal. + Afișati bolusul extins ca % + Asistent setări + Autocompletează glicemiile lipsă + n/a + Multiplicator sigur pentru bazala curentă + Multiplicator sigur maxim zilnic + Rată minimă autosens + Rată maximă autosens + Permite conexiuni în roaming + Setări conexiune + Doar când se încarcă + Setări afișare + Setări generale + Total bolusuri + Total RBTuri + limită fizică + Afișează câmp pentru note în dialogurile de tratamente + Amână bolusul prin divizor + Calcule incluse în rezultatul asistentului: + Irlandeză + Activează NSClient + Ați pornit asistentul pentru setări. Acesta vă va ajuta pentru configurarea setărilor + Setări pompă + Citire stare + Schimbările trebuie făcute în NS + Ignoră asistentul pentru setări + Care este sursa de glicemii? + Apăsați butonul pentru a permite AndroidAPS să sugereze/facă schimbări ale bazalei + Apăsați butonul pentru a activa Obiectivele. După terminarea procesului de setare, alegeți fereastra Obiective pentru a face AndroidAPS complet funcțional. + Activați Obiectivele + Configurați plugin APS + Nu există configurații exportate, decin nu se poate face import de configurații. + Configurați pluginul pentru Sensibilitate + Pluginul Sensibilitate este folosit pentru estimarea sensibilității și calcularea COB. Pentru mai multe info vizitați: + NSClient răspunde de conexiunea cu Nightscout. Puteți ignora această secțiune, dar nu veți putea completa obiectivele până nu îl configurați. + Atenție: noul profil presupune o durată a acțiunii insulinei (DIA) de cel puțin 5 ore. DIA de 5-6 ore este echivalent cu DIA de 3 ore în vechile profiluri. + Configurați sursa glicemiilor + Selectați sursa sau profilul. Dacă pacientul este copil, ar fi bine să alegeți un profil NS. Dacă nu aveți profil NS, puteți alege profil local. De aici alegeți doar sursa profilului; pentru a utiliza acest profil, trebuie să îl activați prin executarea unei \"Schimbări de profil\". + Selectați un algoritm dintre cei disponibili. Aceștia sunt sortați de la cei mai vechi la cei mai noi. Algoritmii mai noi sunt, de obicei, mai puternici și mai agresivi. De aceea, dacă sunteți la început, veți dori să alegeți AMA și nu cu cel mai nou algoritm. NU uitați să citiți documentația OpenAPS și să faceți configurările corecte înainte de folosire! + Începeți primul obiectiv + Permisiune + Solicitați permisiunea + Aplicația necesită permisiune de localizare pentru scanarea prin BT + Aplicația necesită permisiune de acces la mediul de stocare pentru a putea înregistra jurnalele. + Cerință + Configurați plugin insulină + Ieșire From f343cfe0fa56a36956cc17c51dcaf6585ea7b6b6 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Wed, 6 Jun 2018 22:39:51 +0200 Subject: [PATCH 08/44] Ro formatted false --- app/src/main/res/values-ro/strings.xml | 44 +++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 62cbed5d87..9d79b54188 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -539,8 +539,8 @@ Se oprește bolusul Se activează opțiuni pentru uzul în timpul zilei, cum ar fi SMB Trebuie sa citiți wiki și măriți maxIOB pentru a obține SMB corect! Un start bun este maxIOB=media bolusurilor + 3x maxima bazalei din zi - %.2f este limitată la %.2f - Valarea %s este mai mare decât limita fizică + %.2f este limitată la %.2f + Valarea %s este mai mare decât limita fizică Sincronizează cu NS Hipo Autosens ajustează țintele la @@ -617,7 +617,7 @@ Oref Insulină-Rapidă Oref Insulină-UltraRapidă Insulină personalizată - DIA din %f prea scurtă - se folosește %f în schimb! + DIA din %f prea scurtă - se folosește %f în schimb! Activează profil Data INVALID @@ -665,7 +665,7 @@ Pr Grăsime ]]> - Se așteaptă finalul bolusării. Mai sunt %d sec. + Se așteaptă finalul bolusării. Mai sunt %d sec. Se procesează activitatea Pornire livrare bolus Se execută comanda chiar acum @@ -710,21 +710,21 @@ Mod buclă închisă activat IOB maxim configurat corect Glicemie disponibilă din sursa selectată - Valori bazale nealiniate la ore: %s + Valori bazale nealiniate la ore: %s Profil invalid Se programează pompa pentru livrare bolus Reîncarcă Stare Activitate - Fără conexiune de %d min - %d%% (%d min rămase) + Fără conexiune de %d min + %d%% (%d min rămase) Inițializare Suspendat din cauza unei erori Suspendat de utilizator Funcționează Se oprește TBR - Se setează TBR (%d%% / %d min) - Bolusare (%.1f U) + Se setează TBR (%d%% / %d min) + Bolusare (%.1f U) Reîncărcare Operațiunea nu este suportată de pompă Folosire nesigură: un bolus extins sau multiwave este activ. Modul buclă este setat să funcționeze în low-suspend pentru 6 ore. Doar bolusurile normale sunt posibile. @@ -735,7 +735,7 @@ Se setează profilul bazalei Nivelul insulinei din pompă este scăzut Nivelul bateriei pompei este scăzut - Pompa are eroarea: E%d: %s + Pompa are eroarea: E%d: %s Scăzut Gol Normal @@ -744,7 +744,7 @@ Alerta RBT ANULATĂ a fost confirmată Pompa nu poate fi contactată. Nu s-a livrat niciun bolus Livrare eșuată. Se pare că nu a fost livrat bolusul. Pentru siguranță, verificați în pompă pentru a evita bolusarea dublă. Pentru evitarea greșelilor, bolusurile nu sunt retrimise automat. - Doar %.2f U din totalul cerut de %.2f U a fost livrat din cauza unei erori. Verificați pompa pentru confirmare și acționați corespunzător. + Doar %.2f U din totalul cerut de %.2f U a fost livrat din cauza unei erori. Verificați pompa pentru confirmare și acționați corespunzător. Livrarea bolusului și verificarea istoricului pompei a eșuat, verificați pompa și creați manual un bolus folosind Careportal, dacă a fost livrat un bolus. Revenire după pierderea conexiunii Nu este suficientă insulină în rezervor @@ -789,7 +789,7 @@ z săptămână e - %ds expiră %s + %ds expiră %s Stare de menținere Statistici Conectare preventivă @@ -846,7 +846,7 @@ Se folosește versiunea dev. Bucla închisă este dezactivată. Mod inginer activat Modul inginer nu este activat și nu este în versiunea lansată - %.2f U/h + %.2f U/h Se citește profilul bazal Istoricul pompei s-a schimbat după calcularea bolusului. Bolusul nu a fost livrat. Recalculați dacă mai este necesar un bolus. Dacă aceeași cantitate de bolus este necesară, așteptați două minute deoarece două bolusuri cu aceeași valoare nu sunt permise într-un interval mai mic de două minute, din rațiuni de siguranță (indiferent dacă au fost livrate sau nu). Bolus livrat, dar nu s-a reușit înregistrarea evenimentului. Aceasta se poate întâmpla când două bolusuri mici de aceeași valoare sunt livrate în mai puțin de două minute. Verificați istoricul pompei și înregistrările tratamentelor și folosiți Careportal pentru adăugarea intrărilor lipsă. Asigurați-vă că nu adăugați intrări duble. @@ -887,18 +887,18 @@ Modul buclă închisă dezactivat în preferințe Autosens dezactivat în preferințe SMB dezactivat în preferințe - Se limitează maximul ratei bazale la %.2f U/o datorită %s + Se limitează maximul ratei bazale la %.2f U/o datorită %s limită pompă trebuie să fie o valoare pozitivă maximul multiplicatorului bazalei maximul zilnic al multiplicatorului bazalei S-a livrat un bolus în ultimile 3 minute, nu se livrează SMB Bazala setată corect - Se limitează procentul ratei maxime la %d%% datorită %s - Se limitează bolusul la %.1f U datorită %s - Se limitează max IOB la %.1f U datorită %s - Se limitează carbohidrații %d g datorită %s - Se limitează IOB la %.1f U datorită %s + Se limitează procentul ratei maxime la %d%% datorită %s + Se limitează bolusul la %.1f U datorită %s + Se limitează max IOB la %.1f U datorită %s + Se limitează carbohidrații %d g datorită %s + Se limitează IOB la %.1f U datorită %s valoare maximă în preferințe folosire nesigură Citire eșuată a stării @@ -907,8 +907,8 @@ SMB dezactivat întotdeauna și după carbo deoarece sursa glicemiei nu suportă filtrare avansată SMB nu este permis în mod buclă deschisă Mâncare - Se așteaptă sincronizarea (%d s) - Deconectat (%d min) + Se așteaptă sincronizarea (%d s) + Deconectat (%d min) Evenimente Careportal automate Încărcare automată a schimbărilor de insulină, rezervor, baterie și alarme de pompă în Nightscout Maximul total IOB peste care OpenAPS nu poate trece [U] @@ -920,7 +920,7 @@ Timp reset Această valoare este denumită Max IOB în contextul OpenAPS, OpenAPS nu va adăuga mai multă insulină dacă IOB este mai mare ca această valoare - Solicitat: %.2fU Livrat: %.2fU Cod eroare: %d + Solicitat: %.2fU Livrat: %.2fU Cod eroare: %d Primul increment de insulină Al doilea increment de insulină Al treilea increment de insulină From 964efee162adea4422f536fc2289fba9414a0cf3 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Wed, 6 Jun 2018 22:42:36 +0200 Subject: [PATCH 09/44] Ro formatted false 2nd --- app/src/main/res/values-ro/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 9d79b54188..eca918a1c5 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -880,8 +880,8 @@ Eroare E13: Eroare de limbaj Folosește doar conexiune WiFi CGM - Obiectivul %d nu este pornit - Obiectivul %d nu este atins + Obiectivul %d nu este pornit + Obiectivul %d nu este atins Pompa nu suportă bazale temporare Nu s-a citit o rată bazală validă din pompă Modul buclă închisă dezactivat în preferințe @@ -920,7 +920,7 @@ Timp reset Această valoare este denumită Max IOB în contextul OpenAPS, OpenAPS nu va adăuga mai multă insulină dacă IOB este mai mare ca această valoare - Solicitat: %.2fU Livrat: %.2fU Cod eroare: %d + Solicitat: %.2fU Livrat: %.2fU Cod eroare: %d Primul increment de insulină Al doilea increment de insulină Al treilea increment de insulină From 4c2babb905e543155bc00bd1a62a3def7c092982 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Wed, 6 Jun 2018 22:44:06 +0200 Subject: [PATCH 10/44] Ro formatted false 3rd --- app/src/main/res/values-ro/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index eca918a1c5..f9c3148256 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -920,7 +920,7 @@ Timp reset Această valoare este denumită Max IOB în contextul OpenAPS, OpenAPS nu va adăuga mai multă insulină dacă IOB este mai mare ca această valoare - Solicitat: %.2fU Livrat: %.2fU Cod eroare: %d + Solicitat: %.2fU Livrat: %.2fU Cod eroare: %d Primul increment de insulină Al doilea increment de insulină Al treilea increment de insulină From 1d13712aec12e56e880063bfa9b22f37e3faf3c6 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 6 Jun 2018 22:58:50 +0200 Subject: [PATCH 11/44] nsclient setup wizard tweaking --- .../nightscout/androidaps/MainActivity.java | 8 +- .../plugins/Careportal/CareportalPlugin.java | 2 + .../Insulin/InsulinOrefBasePlugin.java | 1 + .../PumpVirtual/VirtualPumpPlugin.java | 1 + .../androidaps/setupwizard/SWDefinition.java | 183 +++++++++++++++++- .../setupwizard/elements/SWPlugin.java | 15 +- 6 files changed, 202 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/MainActivity.java b/app/src/main/java/info/nightscout/androidaps/MainActivity.java index 538f51a82d..34e67e42e5 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/MainActivity.java @@ -139,8 +139,10 @@ public class MainActivity extends AppCompatActivity { AndroidPermission.notifyForStoragePermission(this); AndroidPermission.notifyForBatteryOptimizationPermission(this); - AndroidPermission.notifyForLocationPermissions(this); - AndroidPermission.notifyForSMSPermissions(this); + if (BuildConfig.APS || BuildConfig.PUMPCONTROL) { + AndroidPermission.notifyForLocationPermissions(this); + AndroidPermission.notifyForSMSPermissions(this); + } MainApp.bus().post(new EventFeatureRunning(EventFeatureRunning.Feature.MAIN)); } @@ -200,7 +202,7 @@ public class MainActivity extends AppCompatActivity { menu.clear(); for (PluginBase p : MainApp.getPluginsList()) { pageAdapter.registerNewFragment(p); - if (p.hasFragment() && !p.isFragmentVisible() && p.isEnabled(p.pluginDescription.getType())) { + if (p.hasFragment() && !p.isFragmentVisible() && p.isEnabled(p.pluginDescription.getType()) && !p.pluginDescription.neverVisible) { MenuItem menuItem = menu.add(p.getName()); menuItem.setCheckable(true); menuItem.setOnMenuItemClickListener(item -> { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalPlugin.java index 1428880a81..8cd6e608c5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Careportal/CareportalPlugin.java @@ -23,6 +23,8 @@ public class CareportalPlugin extends PluginBase { .fragmentClass(CareportalFragment.class.getName()) .pluginName(R.string.careportal) .shortName(R.string.careportal_shortname) + .visibleByDefault(true) + .enableByDefault(true) ); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java index 2c46cd7bb6..5d4d1187ac 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Insulin/InsulinOrefBasePlugin.java @@ -29,6 +29,7 @@ public abstract class InsulinOrefBasePlugin extends PluginBase implements Insuli .fragmentClass(InsulinFragment.class.getName()) .pluginName(R.string.fastactinginsulin) .shortName(R.string.insulin_shortname) + .visibleByDefault(false) ); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java index 34d3fee80b..72d74efb36 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java @@ -77,6 +77,7 @@ public class VirtualPumpPlugin extends PluginBase implements PumpInterface { .pluginName(R.string.virtualpump) .shortName(R.string.virtualpump_shortname) .preferencesId(R.xml.pref_virtualpump) + .neverVisible(BuildConfig.NSCLIENTOLNY || BuildConfig.G5UPLOADER) ); pumpDescription.isBolusCapable = true; pumpDescription.bolusStep = 0.1d; diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java index dbdb22782a..0e7ba0e623 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java @@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; +import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.PreferencesActivity; import info.nightscout.androidaps.R; @@ -85,8 +86,14 @@ public class SWDefinition { return this; } - SWDefinition() { + if (BuildConfig.FLAVOR.equals("full")) + SWDefinitionFull(); + else if (BuildConfig.FLAVOR.equals("nsclient")) + SWDefinitionNSClient(); + } + + private void SWDefinitionFull() { // List all the screens here add(new SWScreen(R.string.nav_setupwizard) .add(new SWInfotext() @@ -228,6 +235,7 @@ public class SWDefinition { .add(new SWBreak()) .add(new SWPlugin() .option(PluginType.INSULIN) + .makeVisible(false) .label(R.string.configbuilder_insulin)) .add(new SWBreak()) .add(new SWButton() @@ -441,4 +449,177 @@ public class SWDefinition { ; } + private void SWDefinitionNSClient() { + // List all the screens here + add(new SWScreen(R.string.nav_setupwizard) + .add(new SWInfotext() + .label(R.string.welcometosetupwizard)) + .add(new SWButton() + .text(R.string.nav_import) + .action(() -> ImportExportPrefs.importSharedPreferences(getActivity())) + .visibility(ImportExportPrefs.file::exists)) + .add(new SWInfotext() + .label(R.string.backupismissing) + .visibility(() -> !ImportExportPrefs.file.exists())) + ) + .add(new SWScreen(R.string.language) + .skippable(false) + .add(new SWRadioButton() + .option(R.array.languagesArray, R.array.languagesValues) + .preferenceId(R.string.key_language).label(R.string.language) + .comment(R.string.setupwizard_language_prompt)) + .validator(() -> { + String lang = SP.getString("language", "en"); + LocaleHelper.setLocale(MainApp.instance().getApplicationContext(), lang); + return SP.contains(R.string.key_language); + }) + ) + .add(new SWScreen(R.string.end_user_license_agreement) + .skippable(false) + .add(new SWInfotext() + .label(R.string.end_user_license_agreement_text)) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.end_user_license_agreement_i_understand) + .visibility(() -> !SP.getBoolean(R.string.key_i_understand, false)) + .action(() -> { + SP.putBoolean(R.string.key_i_understand, true); + MainApp.bus().post(new EventSWUpdate(false)); + })) + .visibility(() -> !SP.getBoolean(R.string.key_i_understand, false)) + .validator(() -> SP.getBoolean(R.string.key_i_understand, false)) + ) + .add(new SWScreen(R.string.permission) + .skippable(false) + .add(new SWInfotext() + .label(String.format(MainApp.gs(R.string.needwhitelisting), MainApp.gs(R.string.app_name)))) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.askforpermission) + .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) + .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, AndroidPermission.CASE_BATTERY))) + .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) + .validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS))) + ) + .add(new SWScreen(R.string.permission) + .skippable(false) + .add(new SWInfotext() + .label(MainApp.gs(R.string.needstoragepermission))) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.askforpermission) + .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) + .action(() -> AndroidPermission.askForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE, AndroidPermission.CASE_STORAGE))) + .visibility(() -> Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) + .validator(() -> !(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !AndroidPermission.checkForPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE))) + ) + .add(new SWScreen(R.string.nsclientinternal_title) + .skippable(true) + .add(new SWInfotext() + .label(R.string.nsclientinfotext)) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.enable_nsclient) + .action(() -> { + NSClientPlugin.getPlugin().setPluginEnabled(PluginType.GENERAL, true); + NSClientPlugin.getPlugin().setFragmentVisible(PluginType.GENERAL, true); + ConfigBuilderFragment.processOnEnabledCategoryChanged(NSClientPlugin.getPlugin(), PluginType.GENERAL); + ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard"); + MainApp.bus().post(new EventConfigBuilderChange()); + MainApp.bus().post(new EventSWUpdate(true)); + }) + .visibility(() -> !NSClientPlugin.getPlugin().isEnabled(PluginType.GENERAL))) + .add(new SWEditUrl() + .preferenceId(R.string.key_nsclientinternal_url) + .label(R.string.nsclientinternal_url_title) + .comment(R.string.nsclientinternal_url_dialogmessage)) + .add(new SWEditString() + .validator(text -> text.length() >= 12) + .preferenceId(R.string.key_nsclientinternal_api_secret) + .label(R.string.nsclientinternal_secret_dialogtitle) + .comment(R.string.nsclientinternal_secret_dialogmessage)) + .add(new SWBreak()) + .add(new SWEventListener(this) + .label(R.string.status) + .initialStatus(NSClientPlugin.getPlugin().status) + .listener(new Object() { + @Subscribe + public void onEventNSClientStatus(EventNSClientStatus event) { + MainApp.bus().post(new EventSWLabel(event.status)); + } + }) + ) + .add(new SWBreak()) + .validator(() -> NSClientPlugin.getPlugin().nsClientService != null && NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth) + .visibility(() -> !(NSClientPlugin.getPlugin().nsClientService != null && NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth)) + ) + .add(new SWScreen(R.string.patientage) + .skippable(false) + .add(new SWInfotext() + .label(R.string.patientage_summary)) + .add(new SWBreak()) + .add(new SWRadioButton() + .option(R.array.ageArray, R.array.ageValues) + .preferenceId(R.string.key_age) + .label(R.string.patientage) + .comment(R.string.patientage_summary)) + .validator(() -> SP.contains(R.string.key_age)) + ) + .add(new SWScreen(R.string.configbuilder_insulin) + .skippable(false) + .add(new SWInfotext() + .label(MainApp.gs(R.string.rapid_acting_oref) + ": " + MainApp.gs(R.string.fastactinginsulincomment))) + .add(new SWInfotext() + .label(MainApp.gs(R.string.ultrarapid_oref) + ": " + MainApp.gs(R.string.ultrafastactinginsulincomment))) + .add(new SWInfotext() + .label(MainApp.gs(R.string.free_peak_oref) + ": " + MainApp.gs(R.string.free_peak_oref_description))) + .add(new SWBreak()) + .add(new SWInfotext() + .label(R.string.diawarning)) + .add(new SWBreak()) + .add(new SWPlugin() + .option(PluginType.INSULIN) + .makeVisible(false) + .label(R.string.configbuilder_insulin)) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.insulinsourcesetup) + .action(() -> { + final PluginBase plugin = (PluginBase) MainApp.getConfigBuilder().getActiveInsulin(); + PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { + Intent i = new Intent(activity, PreferencesActivity.class); + i.putExtra("id", plugin.getPreferencesId()); + activity.startActivity(i); + }, null); + }) + .visibility(() -> MainApp.getConfigBuilder().getActiveInsulin()!= null && ((PluginBase) MainApp.getConfigBuilder().getActiveInsulin()).getPreferencesId() > 0)) + .validator(() -> MainApp.getConfigBuilder().getActiveInsulin() != null) + ) + .add(new SWScreen(R.string.configbuilder_sensitivity) + .skippable(false) + .add(new SWInfotext() + .label(R.string.setupwizard_sensitivity_description)) + .add(new SWHtmlLink() + .label(R.string.setupwizard_sensitivity_url)) + .add(new SWBreak()) + .add(new SWPlugin() + .option(PluginType.SENSITIVITY) + .label(R.string.configbuilder_sensitivity)) + .add(new SWBreak()) + .add(new SWButton() + .text(R.string.sensitivitysetup) + .action(() -> { + final PluginBase plugin = (PluginBase) MainApp.getConfigBuilder().getActiveSensitivity(); + PasswordProtection.QueryPassword(activity, R.string.settings_password, "settings_password", () -> { + Intent i = new Intent(activity, PreferencesActivity.class); + i.putExtra("id", plugin.getPreferencesId()); + activity.startActivity(i); + }, null); + }) + .visibility(() -> MainApp.getConfigBuilder().getActiveSensitivity() != null && ((PluginBase) MainApp.getConfigBuilder().getActiveSensitivity()).getPreferencesId() > 0)) + .validator(() -> MainApp.getConfigBuilder().getActiveSensitivity() != null) + ) + ; + } + } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java index b9519bc9b5..06735ee72e 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/elements/SWPlugin.java @@ -25,6 +25,8 @@ public class SWPlugin extends SWItem { private PluginType pType; private RadioGroup radioGroup; + private boolean makeVisible = true; + public SWPlugin() { super(Type.PLUGIN); } @@ -34,6 +36,11 @@ public class SWPlugin extends SWItem { return this; } + public SWPlugin makeVisible(boolean makeVisible) { + this.makeVisible = makeVisible; + return this; + } + @Override public void generateDialog(View view, LinearLayout layout) { Context context = view.getContext(); @@ -58,10 +65,10 @@ public class SWPlugin extends SWItem { radioGroup.setOnCheckedChangeListener((group, checkedId) -> { RadioButton rb = group.findViewById(checkedId); - PluginBase plugin1 = (PluginBase) rb.getTag(); - plugin1.setPluginEnabled(pType, rb.isChecked()); - plugin1.setFragmentVisible(pType, rb.isChecked()); - ConfigBuilderFragment.processOnEnabledCategoryChanged(plugin1, pType); + PluginBase plugin = (PluginBase) rb.getTag(); + plugin.setPluginEnabled(pType, rb.isChecked()); + plugin.setFragmentVisible(pType, rb.isChecked() && makeVisible); + ConfigBuilderFragment.processOnEnabledCategoryChanged(plugin, pType); ConfigBuilderPlugin.getPlugin().storeSettings("SetupWizard"); MainApp.bus().post(new EventConfigBuilderChange()); MainApp.bus().post(new EventSWUpdate()); From 712549e5626167a3a6bc0e8db1b52dee96b41742 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Wed, 6 Jun 2018 23:04:15 +0200 Subject: [PATCH 12/44] Update strings.xml --- app/src/main/res/values-ro/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index f9c3148256..0ceb27ac76 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -920,7 +920,7 @@ Timp reset Această valoare este denumită Max IOB în contextul OpenAPS, OpenAPS nu va adăuga mai multă insulină dacă IOB este mai mare ca această valoare - Solicitat: %.2fU Livrat: %.2fU Cod eroare: %d + Solicitat: %.2fU Livrat: %.2fU Cod eroare: %d Primul increment de insulină Al doilea increment de insulină Al treilea increment de insulină From c96f860585a1f13cc4a53146f75dc1e03152217d Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Wed, 6 Jun 2018 23:19:54 +0200 Subject: [PATCH 13/44] Update strings.xml --- app/src/main/res/values-ro/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 0ceb27ac76..50faf76687 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -920,7 +920,7 @@ Timp reset Această valoare este denumită Max IOB în contextul OpenAPS, OpenAPS nu va adăuga mai multă insulină dacă IOB este mai mare ca această valoare - Solicitat: %.2fU Livrat: %.2fU Cod eroare: %d + Solicitat: %.2fU Livrat: %.2fU Cod eroare: %d Primul increment de insulină Al doilea increment de insulină Al treilea increment de insulină From d6184cc1519a465d1ff46bd0783179fd9832b242 Mon Sep 17 00:00:00 2001 From: AdrianLxM Date: Thu, 7 Jun 2018 22:44:09 +0200 Subject: [PATCH 14/44] Wizard: fully undo "ok" on constraints violation Fixes https://github.com/MilosKozak/AndroidAPS/issues/1056 --- .../androidaps/plugins/Overview/Dialogs/WizardDialog.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java index 36b777733a..303ca10949 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java @@ -315,6 +315,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com confirmMessage += "
" + MainApp.gs(R.string.carbs) + ": " + "" + carbsAfterConstraints + "g" + ""; if (insulinAfterConstraints - calculatedTotalInsulin != 0 || !carbsAfterConstraints.equals(calculatedCarbs)) { + okClicked = false; AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(MainApp.gs(R.string.treatmentdeliveryerror)); builder.setMessage(MainApp.gs(R.string.constraints_violation) + "\n" + MainApp.gs(R.string.changeyourinput)); From 13cb4c28ed0a6f8d0aa2d866bc44312aae375a70 Mon Sep 17 00:00:00 2001 From: TebbeUbben Date: Thu, 7 Jun 2018 22:54:27 +0200 Subject: [PATCH 15/44] ConfigBuilder styling --- .../androidaps/interfaces/PluginBase.java | 6 + .../interfaces/PluginDescription.java | 6 + .../ConfigBuilder/ConfigBuilderFragment.java | 433 +++++------- .../androidaps/tabs/TabPageAdapter.java | 9 +- .../info/nightscout/utils/HardLimits.java | 2 +- .../main/res/drawable-hdpi/ic_visibility.png | Bin 0 -> 953 bytes .../main/res/drawable-mdpi/ic_visibility.png | Bin 0 -> 413 bytes .../main/res/drawable-xhdpi/ic_visibility.png | Bin 0 -> 847 bytes .../res/drawable-xxhdpi/ic_visibility.png | Bin 0 -> 2094 bytes .../res/drawable-xxxhdpi/ic_visibility.png | Bin 0 -> 2090 bytes .../res/drawable/visibility_black_16x16.png | Bin 233 -> 0 bytes .../res/layout/configbuilder_fragment.xml | 622 ++++++++++++------ .../res/layout/configbuilder_simpleitem.xml | 42 -- .../layout/configbuilder_single_plugin.xml | 60 ++ .../main/res/layout/objectives_fragment.xml | 2 +- app/src/main/res/values/strings.xml | 10 + 16 files changed, 645 insertions(+), 547 deletions(-) create mode 100644 app/src/main/res/drawable-hdpi/ic_visibility.png create mode 100644 app/src/main/res/drawable-mdpi/ic_visibility.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_visibility.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_visibility.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_visibility.png delete mode 100644 app/src/main/res/drawable/visibility_black_16x16.png delete mode 100644 app/src/main/res/layout/configbuilder_simpleitem.xml create mode 100644 app/src/main/res/layout/configbuilder_single_plugin.xml diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java index 1173936430..b6c5c6cb96 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginBase.java @@ -57,6 +57,12 @@ public abstract class PluginBase { return getName(); } + public String getDescription() { + return "This is an example description."; + /*if (pluginDescription.description == -1) return null; + else return MainApp.gs(pluginDescription.description);*/ + } + public PluginType getType() { return pluginDescription.mainType; } diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java index c86ae639fa..1634fc672d 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PluginDescription.java @@ -9,6 +9,7 @@ public class PluginDescription { boolean showInList = true; int pluginName = -1; int shortName = -1; + int description = -1; int preferencesId = -1; int advancedPreferencesId = -1; public boolean enableByDefault = false; @@ -74,6 +75,11 @@ public class PluginDescription { return this; } + public PluginDescription description(int description) { + this.description = description; + return this; + } + public String getFragmentClass() { return fragmentClass; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java index e92ca52cd9..b4971f4d7a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderFragment.java @@ -1,30 +1,31 @@ package info.nightscout.androidaps.plugins.ConfigBuilder; -import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.annotation.NonNull; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.CheckBox; -import android.widget.ImageView; +import android.widget.ImageButton; import android.widget.LinearLayout; -import android.widget.ListAdapter; -import android.widget.ListView; +import android.widget.RadioButton; +import android.widget.ScrollView; import android.widget.TextView; import com.crashlytics.android.answers.CustomEvent; import java.util.ArrayList; +import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; +import butterknife.OnCheckedChanged; import butterknife.OnClick; -import info.nightscout.androidaps.Config; +import butterknife.Optional; +import butterknife.Unbinder; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.PreferencesActivity; import info.nightscout.androidaps.R; @@ -50,69 +51,47 @@ import info.nightscout.utils.PasswordProtection; public class ConfigBuilderFragment extends SubscriberFragment { - @BindView(R.id.configbuilder_insulinlistview) - ListView insulinListView; - @BindView(R.id.configbuilder_sensitivitylistview) - ListView sensitivityListView; - @BindView(R.id.configbuilder_bgsourcelistview) - ListView bgsourceListView; - @BindView(R.id.configbuilder_bgsourcelabel) - TextView bgsourceLabel; - @BindView(R.id.configbuilder_pumplistview) - ListView pumpListView; - @BindView(R.id.configbuilder_pumplabel) - TextView pumpLabel; - @BindView(R.id.configbuilder_looplistview) - ListView loopListView; - @BindView(R.id.configbuilder_looplabel) - TextView loopLabel; - @BindView(R.id.configbuilder_treatmentslistview) - ListView treatmentsListView; - @BindView(R.id.configbuilder_treatmentslabel) - TextView treatmentsLabel; - @BindView(R.id.configbuilder_profilelistview) - ListView profileListView; - @BindView(R.id.configbuilder_profilelabel) - TextView profileLabel; - @BindView(R.id.configbuilder_apslistview) - ListView apsListView; - @BindView(R.id.configbuilder_apslabel) - TextView apsLabel; - @BindView(R.id.configbuilder_constraintslistview) - ListView constraintsListView; - @BindView(R.id.configbuilder_constraintslabel) - TextView constraintsLabel; - @BindView(R.id.configbuilder_generallistview) - ListView generalListView; + private List pluginViews = new ArrayList<>(); - @BindView(R.id.configbuilder_mainlayout) - LinearLayout mainLayout; - @BindView(R.id.configbuilder_unlock) + @BindView(R.id.profile_plugins) + LinearLayout profilePlugins; + @BindView(R.id.insulin_plugins) + LinearLayout insulinPlugins; + @BindView(R.id.bgsource_plugins) + LinearLayout bgSourcePlugins; + @BindView(R.id.pump_plugins) + LinearLayout pumpPlugins; + @BindView(R.id.sensitivity_plugins) + LinearLayout sensitivityPlugins; + @BindView(R.id.aps_plugins) + LinearLayout apsPlugins; + @BindView(R.id.loop_plugins) + LinearLayout loopPlugins; + @BindView(R.id.constraints_plugins) + LinearLayout constraintsPlugins; + @BindView(R.id.treatments_plugins) + LinearLayout treatmentsPlugins; + @BindView(R.id.general_plugins) + LinearLayout generalPlugins; + + @BindView(R.id.main_layout) + ScrollView mainLayout; + @BindView(R.id.unlock) Button unlock; - PluginCustomAdapter insulinDataAdapter = null; - PluginCustomAdapter sensivityDataAdapter = null; - PluginCustomAdapter bgsourceDataAdapter = null; - PluginCustomAdapter pumpDataAdapter = null; - PluginCustomAdapter loopDataAdapter = null; - PluginCustomAdapter treatmentDataAdapter = null; - PluginCustomAdapter profileDataAdapter = null; - PluginCustomAdapter apsDataAdapter = null; - PluginCustomAdapter constraintsDataAdapter = null; - PluginCustomAdapter generalDataAdapter = null; - @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { try { View view = inflater.inflate(R.layout.configbuilder_fragment, container, false); - unbinder = ButterKnife.bind(this, view); if (PasswordProtection.isLocked("settings_password")) mainLayout.setVisibility(View.GONE); - else - unlock.setVisibility(View.GONE); + else unlock.setVisibility(View.GONE); + + createViews(); + return view; } catch (Exception e) { FabricPrivacy.logException(e); @@ -121,222 +100,48 @@ public class ConfigBuilderFragment extends SubscriberFragment { return null; } - @OnClick(R.id.configbuilder_unlock) - public void onClickUnlock() { + @OnClick(R.id.unlock) + void onClickUnlock() { PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> { mainLayout.setVisibility(View.VISIBLE); unlock.setVisibility(View.GONE); }, null); } + @Override + public void onDestroyView() { + super.onDestroyView(); + for (PluginView pluginView : pluginViews) pluginView.unbind(); + } @Override protected void updateGUI() { - - insulinDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginType.INSULIN), PluginType.INSULIN); - insulinListView.setAdapter(insulinDataAdapter); - setListViewHeightBasedOnChildren(insulinListView); - bgsourceDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface.class, PluginType.BGSOURCE), PluginType.BGSOURCE); - bgsourceListView.setAdapter(bgsourceDataAdapter); - if (MainApp.getSpecificPluginsVisibleInList(PluginType.BGSOURCE).size() == 0) - bgsourceLabel.setVisibility(View.GONE); - setListViewHeightBasedOnChildren(bgsourceListView); - pumpDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP), PluginType.PUMP); - pumpListView.setAdapter(pumpDataAdapter); - if (MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP).size() == 0 || Config.NSCLIENT || Config.G5UPLOADER) { - pumpLabel.setVisibility(View.GONE); - pumpListView.setVisibility(View.GONE); - } - setListViewHeightBasedOnChildren(pumpListView); - loopDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP), PluginType.LOOP); - loopListView.setAdapter(loopDataAdapter); - setListViewHeightBasedOnChildren(loopListView); - if (MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP).size() == 0) - loopLabel.setVisibility(View.GONE); - treatmentDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT), PluginType.TREATMENT); - treatmentsListView.setAdapter(treatmentDataAdapter); - setListViewHeightBasedOnChildren(treatmentsListView); - if (MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT).size() == 0) - treatmentsLabel.setVisibility(View.GONE); - profileDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginType.PROFILE), PluginType.PROFILE); - profileListView.setAdapter(profileDataAdapter); - if (MainApp.getSpecificPluginsVisibleInList(PluginType.PROFILE).size() == 0) - profileLabel.setVisibility(View.GONE); - setListViewHeightBasedOnChildren(profileListView); - apsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.APS), PluginType.APS); - apsListView.setAdapter(apsDataAdapter); - setListViewHeightBasedOnChildren(apsListView); - if (MainApp.getSpecificPluginsVisibleInList(PluginType.APS).size() == 0) - apsLabel.setVisibility(View.GONE); - sensivityDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(SensitivityInterface.class, PluginType.SENSITIVITY), PluginType.SENSITIVITY); - sensitivityListView.setAdapter(sensivityDataAdapter); - setListViewHeightBasedOnChildren(sensitivityListView); - constraintsDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginType.CONSTRAINTS), PluginType.CONSTRAINTS); - constraintsListView.setAdapter(constraintsDataAdapter); - setListViewHeightBasedOnChildren(constraintsListView); - if (MainApp.getSpecificPluginsVisibleInList(PluginType.CONSTRAINTS).size() == 0) - constraintsLabel.setVisibility(View.GONE); - generalDataAdapter = new PluginCustomAdapter(getContext(), R.layout.configbuilder_simpleitem, MainApp.getSpecificPluginsVisibleInList(PluginType.GENERAL), PluginType.GENERAL); - generalListView.setAdapter(generalDataAdapter); - setListViewHeightBasedOnChildren(generalListView); + for (PluginView pluginView : pluginViews) pluginView.update(); } - /* - * ConfigBuilderFragment code - */ - - private class PluginCustomAdapter extends ArrayAdapter { - - private ArrayList pluginList; - final private PluginType type; - - PluginCustomAdapter(Context context, int textViewResourceId, - ArrayList pluginList, PluginType type) { - super(context, textViewResourceId, pluginList); - this.pluginList = new ArrayList<>(); - this.pluginList.addAll(pluginList); - this.type = type; - } - - private class PluginViewHolder { - TextView name; - CheckBox checkboxEnabled; - CheckBox checkboxVisible; - ImageView settings; - } - - @NonNull - @Override - public View getView(int position, View view, @NonNull ViewGroup parent) { - - PluginViewHolder holder; - PluginBase plugin = pluginList.get(position); - - if (view == null) { - view = LayoutInflater.from(parent.getContext()).inflate(R.layout.configbuilder_simpleitem, null); - - holder = new PluginViewHolder(); - holder.name = (TextView) view.findViewById(R.id.configbuilder_simpleitem_name); - holder.checkboxEnabled = (CheckBox) view.findViewById(R.id.configbuilder_simpleitem_checkboxenabled); - holder.checkboxVisible = (CheckBox) view.findViewById(R.id.configbuilder_simpleitem_checkboxvisible); - holder.settings = (ImageView) view.findViewById(R.id.configbuilder_simpleitem_settings); - - if (plugin.isEnabled(type) && plugin.getPreferencesId() != -1) - holder.settings.setVisibility(View.VISIBLE); - else - holder.settings.setVisibility(View.INVISIBLE); - - view.setTag(holder); - - holder.checkboxEnabled.setOnClickListener(v -> { - CheckBox cb = (CheckBox) v; - PluginBase plugin1 = (PluginBase) cb.getTag(); - plugin1.setPluginEnabled(type, cb.isChecked()); - plugin1.setFragmentVisible(type, cb.isChecked()); - onEnabledCategoryChanged(plugin1, type); - ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled"); - MainApp.bus().post(new EventRefreshGui()); - MainApp.bus().post(new EventConfigBuilderChange()); - ConfigBuilderPlugin.getPlugin().logPluginStatus(); - FabricPrivacy.getInstance().logCustom(new CustomEvent("ConfigurationChange")); - }); - - holder.checkboxVisible.setOnClickListener(v -> { - CheckBox cb = (CheckBox) v; - PluginBase plugin12 = (PluginBase) cb.getTag(); - plugin12.setFragmentVisible(type, cb.isChecked()); - ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxVisible"); - MainApp.bus().post(new EventRefreshGui()); - ConfigBuilderPlugin.getPlugin().logPluginStatus(); - }); - - holder.settings.setOnClickListener(v -> { - final PluginBase plugin13 = (PluginBase) v.getTag(); - PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> { - Intent i = new Intent(getContext(), PreferencesActivity.class); - i.putExtra("id", plugin13.getPreferencesId()); - startActivity(i); - }, null); - }); - - holder.name.setOnLongClickListener(v -> { - final PluginBase plugin14 = (PluginBase) v.getTag(); - PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> { - Intent i = new Intent(getContext(), PreferencesActivity.class); - i.putExtra("id", plugin14.getPreferencesId()); - startActivity(i); - }, null); - return false; - }); - - } else { - holder = (PluginViewHolder) view.getTag(); - } - - holder.name.setText(plugin.getName()); - holder.checkboxEnabled.setChecked(plugin.isEnabled(type)); - holder.checkboxVisible.setChecked(plugin.isFragmentVisible()); - holder.name.setTag(plugin); - holder.checkboxEnabled.setTag(plugin); - holder.checkboxVisible.setTag(plugin); - holder.settings.setTag(plugin); - - if (plugin.pluginDescription.alwaysEnabled) { - holder.checkboxEnabled.setEnabled(false); - } - - if (plugin.pluginDescription.alwayVisible) { - holder.checkboxEnabled.setEnabled(false); - } - - if (!plugin.isEnabled(type)) { - holder.checkboxVisible.setEnabled(false); - } - - if (!plugin.hasFragment()) { - holder.checkboxVisible.setVisibility(View.INVISIBLE); - } - - // Hide enabled control and force enabled plugin if there is only one plugin available - if (type == PluginType.INSULIN || type == PluginType.PUMP || type == PluginType.SENSITIVITY) - if (pluginList.size() < 2) { - holder.checkboxEnabled.setEnabled(false); - plugin.setPluginEnabled(type, true); - ConfigBuilderPlugin.getPlugin().storeSettings("ForceEnable"); - } - - // Constraints cannot be disabled - if (type == PluginType.CONSTRAINTS) - holder.checkboxEnabled.setEnabled(false); - - // Hide disabled profiles by default - if (type == PluginType.PROFILE) { - if (!plugin.isEnabled(type)) { - holder.checkboxVisible.setEnabled(false); - holder.checkboxVisible.setChecked(false); - } else { - holder.checkboxVisible.setEnabled(true); - } - } - - // Disable profile control for pump profiles if pump is not enabled - if (type == PluginType.PROFILE) { - if (PumpInterface.class.isAssignableFrom(plugin.getClass())) { - if (!plugin.isEnabled(PluginType.PUMP)) { - holder.checkboxEnabled.setEnabled(false); - holder.checkboxEnabled.setChecked(false); - } - } - } - - if (plugin.isEnabled(type)) { - view.setBackgroundColor(MainApp.gc(R.color.configBuilderSelectedBackground)); - } - - return view; + private void createViews() { + createViewsForPlugins(profilePlugins, MainApp.getSpecificPluginsVisibleInListByInterface(ProfileInterface.class, PluginType.PROFILE)); + createViewsForPlugins(insulinPlugins, MainApp.getSpecificPluginsVisibleInListByInterface(InsulinInterface.class, PluginType.INSULIN)); + createViewsForPlugins(bgSourcePlugins, MainApp.getSpecificPluginsVisibleInListByInterface(BgSourceInterface.class, PluginType.BGSOURCE)); + createViewsForPlugins(pumpPlugins, MainApp.getSpecificPluginsVisibleInList(PluginType.PUMP)); + createViewsForPlugins(sensitivityPlugins, MainApp.getSpecificPluginsVisibleInListByInterface(SensitivityInterface.class, PluginType.SENSITIVITY)); + createViewsForPlugins(apsPlugins, MainApp.getSpecificPluginsVisibleInList(PluginType.APS)); + createViewsForPlugins(loopPlugins, MainApp.getSpecificPluginsVisibleInList(PluginType.LOOP)); + createViewsForPlugins(constraintsPlugins, MainApp.getSpecificPluginsVisibleInListByInterface(ConstraintsInterface.class, PluginType.CONSTRAINTS)); + createViewsForPlugins(treatmentsPlugins, MainApp.getSpecificPluginsVisibleInList(PluginType.TREATMENT)); + createViewsForPlugins(generalPlugins, MainApp.getSpecificPluginsVisibleInList(PluginType.GENERAL)); + } + private void createViewsForPlugins(LinearLayout parent, List plugins) { + for (PluginBase plugin: plugins) { + PluginView pluginView = new PluginView(plugin); + parent.addView(pluginView.getBaseView()); + pluginViews.add(pluginView); } + } + private boolean areMultipleSelectionsAllowed(PluginType type) { + return type == PluginType.GENERAL || type == PluginType.CONSTRAINTS ||type == PluginType.LOOP; } public static void processOnEnabledCategoryChanged(PluginBase changedPlugin, PluginType type) { @@ -394,35 +199,95 @@ public class ConfigBuilderFragment extends SubscriberFragment { } } - void onEnabledCategoryChanged(PluginBase changedPlugin, PluginType type) { - processOnEnabledCategoryChanged(changedPlugin, type); - updateGUI(); - } + class PluginView { - /**** - * Method for Setting the Height of the ListView dynamically. - * *** Hack to fix the issue of not showing all the items of the ListView - * *** when placed inside a ScrollView - ****/ - public static void setListViewHeightBasedOnChildren(ListView listView) { - ListAdapter listAdapter = listView.getAdapter(); - if (listAdapter == null) - return; + private Unbinder unbinder; + private PluginBase plugin; + private boolean updating = false; - int desiredWidth = View.MeasureSpec.makeMeasureSpec(listView.getWidth(), View.MeasureSpec.UNSPECIFIED); - int totalHeight = 0; - View view = null; - for (int i = 0; i < listAdapter.getCount(); i++) { - view = listAdapter.getView(i, view, listView); - if (i == 0) - view.setLayoutParams(new ViewGroup.LayoutParams(desiredWidth, ViewGroup.LayoutParams.WRAP_CONTENT)); + LinearLayout baseView; + @BindView(R.id.plugin_enabled_exclusive) + RadioButton enabledExclusive; + @BindView(R.id.plugin_enabled_inclusive) + CheckBox enabledInclusive; + @BindView(R.id.plugin_name) + TextView pluginName; + @BindView(R.id.plugin_description) + TextView pluginDescription; + @BindView(R.id.plugin_preferences) + ImageButton pluginPreferences; + @BindView(R.id.plugin_visibility) + CheckBox pluginVisibility; - view.measure(desiredWidth, View.MeasureSpec.UNSPECIFIED); - totalHeight += view.getMeasuredHeight(); + public PluginView(PluginBase plugin) { + this.plugin = plugin; + baseView = (LinearLayout) getLayoutInflater().inflate(R.layout.configbuilder_single_plugin, null); + unbinder = ButterKnife.bind(this, baseView); + update(); } - ViewGroup.LayoutParams params = listView.getLayoutParams(); - params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); - listView.setLayoutParams(params); + + public LinearLayout getBaseView() { + return baseView; + } + + public void update() { + updating = true; + enabledExclusive.setVisibility(areMultipleSelectionsAllowed(plugin.getType()) ? View.GONE : View.VISIBLE); + enabledInclusive.setVisibility(areMultipleSelectionsAllowed(plugin.getType()) ? View.VISIBLE : View.GONE); + enabledExclusive.setChecked(plugin.isEnabled(plugin.getType())); + enabledInclusive.setChecked(plugin.isEnabled(plugin.getType())); + enabledInclusive.setEnabled(!plugin.pluginDescription.alwaysEnabled); + enabledExclusive.setEnabled(!plugin.pluginDescription.alwaysEnabled); + pluginName.setText(plugin.getName()); + if (plugin.getDescription() == null) pluginDescription.setVisibility(View.GONE); + else { + pluginDescription.setVisibility(View.VISIBLE); + pluginDescription.setText(plugin.getDescription()); + } + pluginPreferences.setVisibility(plugin.getPreferencesId() == -1 || !plugin.isEnabled(plugin.getType()) ? View.GONE : View.VISIBLE); + pluginVisibility.setVisibility(plugin.hasFragment() ? View.VISIBLE : View.INVISIBLE); + pluginVisibility.setEnabled(!(plugin.pluginDescription.neverVisible || plugin.pluginDescription.alwayVisible) && plugin.isEnabled(plugin.getType())); + pluginVisibility.setChecked(plugin.isFragmentVisible()); + updating = false; + } + + @OnCheckedChanged(R.id.plugin_visibility) + void onVisibilityChanged() { + if (updating) return; + plugin.setFragmentVisible(plugin.getType(), pluginVisibility.isChecked()); + ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxVisible"); + MainApp.bus().post(new EventRefreshGui()); + ConfigBuilderPlugin.getPlugin().logPluginStatus(); + } + + @OnCheckedChanged({R.id.plugin_enabled_exclusive, R.id.plugin_enabled_inclusive}) + void onEnabledChanged() { + if (updating) return; + boolean enabled = enabledExclusive.getVisibility() == View.VISIBLE ? enabledExclusive.isChecked() : enabledInclusive.isChecked(); + plugin.setPluginEnabled(plugin.getType(), enabled); + plugin.setFragmentVisible(plugin.getType(), enabled); + processOnEnabledCategoryChanged(plugin, plugin.getType()); + updateGUI(); + ConfigBuilderPlugin.getPlugin().storeSettings("CheckedCheckboxEnabled"); + MainApp.bus().post(new EventRefreshGui()); + MainApp.bus().post(new EventConfigBuilderChange()); + ConfigBuilderPlugin.getPlugin().logPluginStatus(); + FabricPrivacy.getInstance().logCustom(new CustomEvent("ConfigurationChange")); + } + + @OnClick(R.id.plugin_preferences) + void onPluginPreferencesClicked() { + PasswordProtection.QueryPassword(getContext(), R.string.settings_password, "settings_password", () -> { + Intent i = new Intent(getContext(), PreferencesActivity.class); + i.putExtra("id", plugin.getPreferencesId()); + startActivity(i); + }, null); + } + + public void unbind() { + unbinder.unbind(); + } + } } diff --git a/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java b/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java index c17646e901..79037ebcd8 100644 --- a/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java +++ b/app/src/main/java/info/nightscout/androidaps/tabs/TabPageAdapter.java @@ -3,9 +3,11 @@ package info.nightscout.androidaps.tabs; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; +import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.app.FragmentStatePagerAdapter; import android.view.ViewGroup; @@ -19,7 +21,7 @@ import info.nightscout.androidaps.interfaces.PluginBase; /** * Created by mike on 30.05.2016. */ -public class TabPageAdapter extends FragmentStatePagerAdapter { +public class TabPageAdapter extends FragmentPagerAdapter { ArrayList visibleFragmentList = new ArrayList<>(); @@ -76,5 +78,8 @@ public class TabPageAdapter extends FragmentStatePagerAdapter { } } - + @Override + public long getItemId(int position) { + return System.identityHashCode(visibleFragmentList.get(position)); + } } diff --git a/app/src/main/java/info/nightscout/utils/HardLimits.java b/app/src/main/java/info/nightscout/utils/HardLimits.java index 8e1a05db0d..ed58687f8f 100644 --- a/app/src/main/java/info/nightscout/utils/HardLimits.java +++ b/app/src/main/java/info/nightscout/utils/HardLimits.java @@ -40,7 +40,7 @@ public class HardLimits { public static final double MAXISF = 720; // mgdl public static final double[] MAXIOB_AMA = {3, 5, 7, 12}; - public static final double[] MAXIOB_SMB = {3, 7, 12, 25}; + public static final double[] MAXIOB_SMB = {3, 7, 20, 25}; public static final double[] MAXBASAL = {2, 5, 10, 12}; diff --git a/app/src/main/res/drawable-hdpi/ic_visibility.png b/app/src/main/res/drawable-hdpi/ic_visibility.png new file mode 100644 index 0000000000000000000000000000000000000000..a014628e30b96b396a207ea86b52c54e81c2b28e GIT binary patch literal 953 zcmV;q14jIbP)eP6?gL`upo2_f0a0b^*4$r93#LP<@A14|MPXc9TGWEsnFVmUAeI1nLA zvgbgN2^q$ivE|bBx&L~<_kExD{~a)WQ{R2^9{lg;ey-=buX}mLEHlkAJj?;=%g7u< z{|iI5w*C}#T3x|sT|K;0_EKgWBE!xD>dhQq+o< z%VU$`tp{!f?w7Q>6{s1&_94Jcz-ho1V*>mRyajv!tO5dRHz4PZEEb24{RzARER~eA zBQ_S0?daqoU>{(Up;Ni|3t$QGI!iBAIuHXipLuu#(H-S=q>*?t6AG|*QD~wj=Ohflr!Z zKUGCtDCx)YI|X>Ip{b;Ag`|ZefNY;tscL27ZQu+^-`L&?cpRADa9#gZ$FhV#$BWs;WL-n`mIilAkY!l{zJno3!* zld9UjaU!C-ThcYreZBeii!DsGpwwEV9I?wZi2(xa}GbZ-Y}0q_8@-3$R;0W9kQ zbcdwt3eZ(~&;&pkIZGrh>j2HJl+`OzT@h-_-UQ}JT4j6N($MJ*=a);=Yi#cXJOxB| zExTA!Bs0>7(lb(R!`(T)85Q#-y;u+EE;+I5C0PPJuZTqG$&wQ08Z1s(>DX*}+G;Cx`Eq*UdUwT9~n zrKjvZ^v)?QRt{+%a z$E9f|3tD>3oxpwBp9UxVV8FgLbjr8%aBIz@4AqQ-zOw(SQtsa`UO~%-&Sf`O!d*;$MApteGX6`rE?5z bbPW9sBP~=k&$Y&)00000NkvXXu0mjfyXMBt literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_visibility.png b/app/src/main/res/drawable-mdpi/ic_visibility.png new file mode 100644 index 0000000000000000000000000000000000000000..d5a9dc9ca4226dbae86a19e095a11d8f721b15a0 GIT binary patch literal 413 zcmV;O0b>4%P)qa1UHcdZ|ZqO^R#}04u;W z&{ZSIGjIf~OS;Q?^9vwmyap@+ttqF^_}!Aa{{VJ?)pSKw0Ji&pQ=pItVBi4Q1a9K} z5KsbUp=waBfC)(t75^Uq+ugt!FqjHnlC+gozU^WJP9}N_j7us9pCrIxT?*VhE1db%l`~cXV1dcPZ9FufmJ5;cgvTsW&+8zbYGkm8coqShd zJ8(Cg(a;V_@3xo!R@CGV7wz(k3c;F zIXzHMp_~rPEj}s{FtbI#dSDf>1Xu_(0MmknKY`D{Ti_+|1b86nO^zAM<IIz?&3(-*!c)hPEE*edCDmRu$PGiwHJ0JE}`0pEZt zz#ZV3q%SUGX0w46z$Rb^Ff&2dSD;nWy=uHw0hpN=Xcv&>K`%(>J5n;b(xU;)iO>MD z9Ow~jljMb7mMSVRvn|1!p8M74H?UXI#RRVou$b9y;5;xfL(XeqyClzoVN@1?nXLmn zbdxibyXW`RYJ5p&0C6Fq1^)t?Bt0Bz&oBUHHV=3X%uVoUr=(pmpP4!6eIeI}LfyfZ|{G%$ymslOdnm7_>b_Up=_->1&+a=zC2$-37 znpc4L{1j@IbUy-c5IB`02pp1hI+AS)HJ2jp(ON92f5yZBd^PZVOr?e)>EoXDUY|lf zBL>neq>(RssnjmX+x8#;FTzrmqNGpKpblkbzRyfe5e9lCl{VFW5i|4R&YCwR^*xf7 zjW&Q@V9Iy`D0~VPyNE*`7NL!9mUL@a8;x38aR*t5La|qg0AelRL#lYoT$DvRO7xIZ)zh~oZIMj(p&Qy+mS?pYf`cY5Ie5stg>{+r`&;@UjsY*~k;F*hLZ19bp-J(yR%9)Y|b%qw4yKwb~#l`nh* Z{sK;sc0e^r-If3V002ovPDHLkV1fe;bmjm6 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_visibility.png b/app/src/main/res/drawable-xxhdpi/ic_visibility.png new file mode 100644 index 0000000000000000000000000000000000000000..dbc192368f897f52b0c1c502ba56492247021f47 GIT binary patch literal 2094 zcmV+}2+{Y6P)C)(p%GMSi>U#OAZn|v)*9!zz#lf&iGbFDYKuYz z5@ZO-P*96$Vxnl8Qd^BiY89-F^UzxAu*~QNSU9f3y4t*bDpv_%rZ(;C^7Iq zfRlhDfk!4#9sxWII0$%1n*RTQ{{sI849LHL-M}A#9|Cs(8zud--g4_deLw(;29a+W0c=HD11KU61>Ogo2Rs>gcq=okuEapy2V4)Vko4E;ua17QF+j<`yaf0{I#O-S ztErCdz`KAAlI**(r4c|8F&lUfa87c%*%LVcFFpX=2z*M?rd<7503}~zP*$Yl|h^~ggdJ(OOUPnS7yNiHt;m z+p#|bcu{irP7Rzd<@z<}RG&@OR4X;81yDpdvAZyZZUa?UyrcI3R{*y;JeP&$WUU6v zQStRDkLo3qb;dVH-vpLR+FA9*$^a#Bz6QK1C3RKD=soA7v)a1|>?i|fPx9nN-;`5%H#UWFD6RlzrVz zb`z5RP&QU6KoQ|O>2tuF`)Z{!z5T!c1^A$kRa6ZvGw@fHEn@2d0r!2zd0%Ou`k`|0t8$TyG&Us$u(c0j8vS?ylW^= zz;#t!u_=F5(vndxrikd$WUHDY$#SV41(-KzJ*ndV5^!z>%NZQomUOHAl_W>TNl8|8HE?$Bgn@g3GbH`I zU&j=HBEt30+f(E+)0ZntBwbcuJtw9_Ew@B*t>#5+DA4WPXvhL;EWnZM)2=Tbn3Owc%?d+2<7kbXKZYa%!EP zP9KF?lDykfBqFu}$2VNWFC;y)K(`BAb3aX30Ov-FC9NF=(2s%VH(bCTNrgu!A{@4x z99>UsuOv4Ch9n|fsplTwp1#eJCR3ZiBj#M-ISm2YEos(>1(?Ljr7U_X_em-QIU?L9 zDjd7Unzl)Dq@9r?_A}tP8j~%0)D+3FGj+rcPnE8_5lv*aq#=hH5f1T=l1*f-BqxSb zBq9vFH=v0)Z=2hn{TGG#Wr^BwF_ zG4RomVcwdjAyNEds>16=o0(4(6F{~qb3bcxx57PiV2-3AlaB~T2zMKtvDXokTMHy@ zEU=!Z0(UlSJG}$=${?{nu2^-s@#;*j#l@;S39iD2x||U)C*@oAd1aR5_uZ2}Pty7V zaJ&Y$x9#5w!+*&xSpS`pPA__{qdWHZ^=+9$nZE%W2atExy)W~~kFIkT(zC8-R!MsI zsCN_BZC=RZm;&)p@tmCMe;>F8*d)mp6$&LH+yr=UCgW+s?8COce#hKDP#NXwlEb|3 zqD;ol=4+yVog_zz)+Euvz0xR$a`gt90Wi%`pK|T3J5X8`$3CkRrm>x;bkz zkOsyjiZ6ZUQ@#KX7WCk z9JsrkIgT_J5WnX{)W^w}IPHk1w1#pOw+2w3Z|bfAm+eOCui1*+!EjPH5AgT4HpI@> z7UFw8zQ$r&#ktjFKdWqxRex`5!ehrvw>VzrrXTR)1eQa&349+#f1IKB=3@XHfqZQI zF@54t?R$;B&*;wW_sYtIsvwMeZdw2u@Ku9MW=k0-Xgl!>{u}odtCk)C_^nf|}v? Yf97D4XDiAHeOH_*}95mhC$MRZY1 zB#k9Vv`;G?)ka&|4h@}_3?bIBG(7JQc<;O)KKGvU`P}pQ;huZW=Uxx=_kzl6$^!rZ zMR|J!9rWn`Kvw#o&fdc)`asG*?`Y^tNn)uMQ=@$86{KLR=zkWv? zt3qO%$q&%1%S4|Ja+$Ro&*h#Pi+}BRZewBL)F>Q_GgdQEpp{~5X{FLN@y(1`&i43; z-NpVde@`V~#+LAy{QNnJO;>$b*N0XH#-s7kp};ds<@QhlxAZRP4e$V2z+J4Bwgyam z?;hKwf)4mY4}Kp=bOGO`Nt$$FHUHO0G))p7qZOSMZ5y4y{}+3$;7P#~LIP;a8-G&j zhYk+1r7FthhqA{Ay9K)j;!awt5iLp+N+fDXV5O&J7iCzoG(?%i7Btl;)ikxT>5Dm7 z?+l1Y)FFH&Fu}QTYPjko=u0KSLcv9Yu<%E3h7Ppy0;a^W@8kSN6RUmQ@qL3Q-H z6W$`tNdc?}ua~QX)G02~U!oNG8w&hjwmNCgoo?{0dEHUwMnrAnh6ntXk^UML57x`Jos-a&hRuB35^XRI$`UHHxoO-4mc{2Q3WToo zY~L_|NSp&rAegiwAa6)~Hcewt$q8_Rk9-EJ%w*#r7E+PWMJ1Lo<+g9xi)%fN2xr;= zrQH@#=~NJHxV3$AW_z+V5aQUEaYtgT_}+YLKEr)a`0<1J!adSuUYGbeWt{3^V>Wo)TUnvR%A`YAyTjKrtSr+f)bc{bKBe_k{XhT)yg&~s{ z9%7zmu&In?z}|+FP3%XAY3+GAU}cp}MsiYGu{vvRuxtIP)#<~D zj=c_Dr@NIVLwVev;tgT$fXGFsZwyuK?ZCiZQ|XM=yrM%uS1vDq5mq>^#k!Jin$VDmgLj?~x=^r!+}$Xs|5R9%JgC4CXEO z4p*`obwL(_3yz{)V^Z7vPKzpmC}P(+a|J0m5t&mC;vYmiwXGrTgz}T%<(q%H&-(ey zN%p<7A6XLoOk%yE^85gv$`_8&Tw*$}pX3nGqH>8BwTyV`^0nGkyYq$|A|RRAtRY;=usrB6-J~uM3QW9 z@Y7Oy@Q9t2@ep}ZdZ1!!vZLwK%FVpxS3Pdp(>Ic^)K5ifjyvuJKs|cA+IN*TaWCxP z+SpCNV49zg_3cLC~RQj$g=8^EWem5i;_UnfV5 zHY7~u4DbGZmcEA6uz_nErODgaZu@mK8fcV1@l>_ZgDIubd@*U8luAlwR$(feHXFn6h?;z$eD49`!9beJxbC?n^ zefbYqYa>Wy#g#vfz$n?3cMFhABs}S8R3LHx87c2Ut@ns@a9x`C`f-Z}$Cyt9~oheGeoeH=Vu(1C)~Fp5DEtQ0II$ zZs3pbKneC=q2scS>oeyQg%C5euJATBkzn8Rn#H1G)Z`@WUavjy^Mw3#~!nhT|VO+-JHY6gkpwcR< z`SZe>@wZ+)W2jZ1>}u7%U2gSd2Nghn@(D zs%m@qbA%;Rhn7iOW zI4bYLE8dJAhbWhTE$>5318z}fd}iu3d*?Bamq%!q>`uBv=}(|0M0GavHNT*`_BV@+|;f4gim^`b81 zMZNi^m6i1K_yu!adaa{C5EFWQ7gn<1YnFO4_p4u6Zf|$R8{6l{&m^;pkBV08Z2^<^ kLh1i27yoN?R)MxG^l$9oPj$^>4}Jgu<>~Ly<`!M}Z@sqTT>t<8 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/visibility_black_16x16.png b/app/src/main/res/drawable/visibility_black_16x16.png deleted file mode 100644 index d24867dcdf25e7cf90ddd1c90d999359b2410d3f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 233 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6Hh8)?hG>ZHJ?QP_#K^#UA$dlw z!^Ox823=u7mli2?D4ek4o@lVxlkb*Op!5sVugwxwpJxi2Kd{WX*vTHBmS%U?dRyZ8 zxvdf}D@{bW&9km$#kuTRrESXN@+D+#OsB+3>);<3ubGGyCcZqdzC(^nkoA{R+PCr} z`&qTT99=b&UIrZraE^X>d*!swj$-ZI^IUjLrbgX!DG6PBwdBmvi2Iv6XY3B!`tZbB h{@~#ER(!eV + android:gravity="center" + android:orientation="vertical"> + +