Merge branch 'dev' into localprofile
This commit is contained in:
commit
0fdc789e1f
11 changed files with 187 additions and 62 deletions
|
@ -4,6 +4,7 @@ import android.graphics.Color
|
|||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.SystemClock
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
@ -12,6 +13,7 @@ import android.widget.Button
|
|||
import android.widget.EditText
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.LinearSmoothScroller
|
||||
|
@ -21,6 +23,8 @@ import info.nightscout.androidaps.R
|
|||
import info.nightscout.androidaps.logging.L
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.activities.ObjectivesExamDialog
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.dialogs.NtpProgressDialog
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.events.EventNtpStatus
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesUpdateGui
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective.ExamTask
|
||||
import info.nightscout.androidaps.receivers.NetworkChangeReceiver
|
||||
|
@ -101,18 +105,20 @@ class ObjectivesFragment : Fragment() {
|
|||
}
|
||||
|
||||
private fun scrollToCurrentObjective() {
|
||||
for (i in 0 until ObjectivesPlugin.objectives.size) {
|
||||
val objective = ObjectivesPlugin.objectives[i]
|
||||
if (!objective.isStarted || !objective.isAccomplished) {
|
||||
context?.let {
|
||||
val smoothScroller = object : LinearSmoothScroller(it) {
|
||||
override fun getVerticalSnapPreference(): Int = SNAP_TO_START
|
||||
override fun calculateTimeForScrolling(dx: Int): Int = super.calculateTimeForScrolling(dx) * 4
|
||||
activity?.runOnUiThread {
|
||||
for (i in 0 until ObjectivesPlugin.objectives.size) {
|
||||
val objective = ObjectivesPlugin.objectives[i]
|
||||
if (!objective.isStarted || !objective.isAccomplished) {
|
||||
context?.let {
|
||||
val smoothScroller = object : LinearSmoothScroller(it) {
|
||||
override fun getVerticalSnapPreference(): Int = SNAP_TO_START
|
||||
override fun calculateTimeForScrolling(dx: Int): Int = super.calculateTimeForScrolling(dx) * 4
|
||||
}
|
||||
smoothScroller.targetPosition = i
|
||||
objectives_recyclerview.layoutManager?.startSmoothScroll(smoothScroller)
|
||||
}
|
||||
smoothScroller.targetPosition = i
|
||||
objectives_recyclerview.layoutManager?.startSmoothScroll(smoothScroller)
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -126,7 +132,6 @@ class ObjectivesFragment : Fragment() {
|
|||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val objective = ObjectivesPlugin.objectives[position]
|
||||
holder.title.text = MainApp.gs(R.string.nth_objective, position + 1)
|
||||
holder.revert.visibility = View.GONE
|
||||
if (objective.objective != 0) {
|
||||
holder.objective.visibility = View.VISIBLE
|
||||
holder.objective.text = MainApp.gs(objective.objective)
|
||||
|
@ -142,6 +147,8 @@ class ObjectivesFragment : Fragment() {
|
|||
holder.verify.visibility = View.GONE
|
||||
holder.progress.visibility = View.GONE
|
||||
holder.accomplished.visibility = View.GONE
|
||||
holder.unFinish.visibility = View.GONE
|
||||
holder.unStart.visibility = View.GONE
|
||||
if (position == 0 || ObjectivesPlugin.objectives[position - 1].isAccomplished)
|
||||
holder.start.visibility = View.VISIBLE
|
||||
else
|
||||
|
@ -152,15 +159,16 @@ class ObjectivesFragment : Fragment() {
|
|||
holder.progress.visibility = View.GONE
|
||||
holder.start.visibility = View.GONE
|
||||
holder.accomplished.visibility = View.VISIBLE
|
||||
holder.unFinish.visibility = View.VISIBLE
|
||||
holder.unStart.visibility = View.GONE
|
||||
} else if (objective.isStarted) {
|
||||
holder.gate.setTextColor(-0x1)
|
||||
holder.verify.visibility = View.VISIBLE
|
||||
holder.verify.isEnabled = objective.isCompleted || objectives_fake.isChecked
|
||||
holder.start.visibility = View.GONE
|
||||
holder.accomplished.visibility = View.GONE
|
||||
if (objective.isRevertable) {
|
||||
holder.revert.visibility = View.VISIBLE
|
||||
}
|
||||
holder.unFinish.visibility = View.GONE
|
||||
holder.unStart.visibility = View.VISIBLE
|
||||
holder.progress.visibility = View.VISIBLE
|
||||
holder.progress.removeAllViews()
|
||||
for (task in objective.tasks) {
|
||||
|
@ -203,39 +211,43 @@ class ObjectivesFragment : Fragment() {
|
|||
holder.accomplished.text = MainApp.gs(R.string.accomplished, DateUtil.dateAndTimeString(objective.accomplishedOn))
|
||||
holder.accomplished.setTextColor(-0x3e3e3f)
|
||||
holder.verify.setOnClickListener {
|
||||
holder.verify.visibility = View.INVISIBLE
|
||||
NetworkChangeReceiver.grabNetworkStatus(context)
|
||||
if (objectives_fake.isChecked) {
|
||||
objective.accomplishedOn = DateUtil.now()
|
||||
scrollToCurrentObjective()
|
||||
startUpdateTimer()
|
||||
RxBus.send(EventObjectivesUpdateGui())
|
||||
} else
|
||||
SntpClient.ntpTime(object : SntpClient.Callback() {
|
||||
override fun run() {
|
||||
activity?.runOnUiThread {
|
||||
holder.verify.visibility = View.VISIBLE
|
||||
} else {
|
||||
// move out of UI thread
|
||||
Thread {
|
||||
NtpProgressDialog().show((context as AppCompatActivity).supportFragmentManager, "NtpCheck")
|
||||
RxBus.send(EventNtpStatus(MainApp.gs(R.string.timedetection), 0))
|
||||
SntpClient.ntpTime(object : SntpClient.Callback() {
|
||||
override fun run() {
|
||||
log.debug("NTP time: $time System time: ${DateUtil.now()}")
|
||||
SystemClock.sleep(300)
|
||||
if (!networkConnected) {
|
||||
ToastUtils.showToastInUiThread(context, R.string.notconnected)
|
||||
RxBus.send(EventNtpStatus(MainApp.gs(R.string.notconnected), 99))
|
||||
} else if (success) {
|
||||
if (objective.isCompleted(time)) {
|
||||
objective.accomplishedOn = time
|
||||
scrollToCurrentObjective()
|
||||
startUpdateTimer()
|
||||
RxBus.send(EventNtpStatus(MainApp.gs(R.string.success), 100))
|
||||
SystemClock.sleep(1000)
|
||||
RxBus.send(EventObjectivesUpdateGui())
|
||||
SystemClock.sleep(100)
|
||||
scrollToCurrentObjective()
|
||||
} else {
|
||||
ToastUtils.showToastInUiThread(context, R.string.requirementnotmet)
|
||||
RxBus.send(EventNtpStatus(MainApp.gs(R.string.requirementnotmet), 99))
|
||||
}
|
||||
} else {
|
||||
ToastUtils.showToastInUiThread(context, R.string.failedretrievetime)
|
||||
RxBus.send(EventNtpStatus(MainApp.gs(R.string.failedretrievetime), 99))
|
||||
}
|
||||
}
|
||||
}
|
||||
}, NetworkChangeReceiver.isConnected())
|
||||
}, NetworkChangeReceiver.isConnected())
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
holder.start.setOnClickListener {
|
||||
holder.start.visibility = View.INVISIBLE
|
||||
NetworkChangeReceiver.grabNetworkStatus(context)
|
||||
if (objectives_fake.isChecked) {
|
||||
objective.startedOn = DateUtil.now()
|
||||
|
@ -243,36 +255,43 @@ class ObjectivesFragment : Fragment() {
|
|||
startUpdateTimer()
|
||||
RxBus.send(EventObjectivesUpdateGui())
|
||||
} else
|
||||
SntpClient.ntpTime(object : SntpClient.Callback() {
|
||||
override fun run() {
|
||||
activity?.runOnUiThread {
|
||||
holder.start.visibility = View.VISIBLE
|
||||
// move out of UI thread
|
||||
Thread {
|
||||
NtpProgressDialog().show((context as AppCompatActivity).supportFragmentManager, "NtpCheck")
|
||||
RxBus.send(EventNtpStatus(MainApp.gs(R.string.timedetection), 0))
|
||||
SntpClient.ntpTime(object : SntpClient.Callback() {
|
||||
override fun run() {
|
||||
log.debug("NTP time: $time System time: ${DateUtil.now()}")
|
||||
SystemClock.sleep(300)
|
||||
if (!networkConnected) {
|
||||
ToastUtils.showToastInUiThread(context, R.string.notconnected)
|
||||
RxBus.send(EventNtpStatus(MainApp.gs(R.string.notconnected), 99))
|
||||
} else if (success) {
|
||||
objective.startedOn = time
|
||||
scrollToCurrentObjective()
|
||||
startUpdateTimer()
|
||||
RxBus.send(EventNtpStatus(MainApp.gs(R.string.success), 100))
|
||||
SystemClock.sleep(1000)
|
||||
RxBus.send(EventObjectivesUpdateGui())
|
||||
SystemClock.sleep(100)
|
||||
scrollToCurrentObjective()
|
||||
} else {
|
||||
ToastUtils.showToastInUiThread(context, R.string.failedretrievetime)
|
||||
RxBus.send(EventNtpStatus(MainApp.gs(R.string.failedretrievetime), 99))
|
||||
}
|
||||
}
|
||||
}
|
||||
}, NetworkChangeReceiver.isConnected())
|
||||
}, NetworkChangeReceiver.isConnected())
|
||||
}.start()
|
||||
}
|
||||
holder.revert.setOnClickListener {
|
||||
objective.accomplishedOn = 0
|
||||
objective.startedOn = 0
|
||||
if (position > 0) {
|
||||
val prevObj = ObjectivesPlugin.objectives[position - 1]
|
||||
prevObj.accomplishedOn = 0
|
||||
holder.unStart.setOnClickListener {
|
||||
OKDialog.showConfirmation(activity, MainApp.gs(R.string.doyouwantresetstart)) {
|
||||
objective.startedOn = 0
|
||||
scrollToCurrentObjective()
|
||||
RxBus.send(EventObjectivesUpdateGui())
|
||||
}
|
||||
}
|
||||
holder.unFinish.setOnClickListener {
|
||||
objective.accomplishedOn = 0
|
||||
scrollToCurrentObjective()
|
||||
RxBus.send(EventObjectivesUpdateGui())
|
||||
}
|
||||
if (objective.hasSpecialInput && !objective.isAccomplished && objective.isStarted) {
|
||||
if (objective.hasSpecialInput && !objective.isAccomplished && objective.isStarted && objective.specialActionEnabled()) {
|
||||
// generate random request code if none exists
|
||||
val request = SP.getString(R.string.key_objectives_request_code, String.format("%1$05d", (Math.random() * 99999).toInt()))
|
||||
SP.putString(R.string.key_objectives_request_code, request)
|
||||
|
@ -307,7 +326,8 @@ class ObjectivesFragment : Fragment() {
|
|||
val progress: LinearLayout = itemView.findViewById(R.id.objective_progress)
|
||||
val verify: Button = itemView.findViewById(R.id.objective_verify)
|
||||
val start: Button = itemView.findViewById(R.id.objective_start)
|
||||
val revert: Button = itemView.findViewById(R.id.objective_back)
|
||||
val unFinish: Button = itemView.findViewById(R.id.objective_unfinish)
|
||||
val unStart: Button = itemView.findViewById(R.id.objective_unstart)
|
||||
val inputHint: TextView = itemView.findViewById(R.id.objective_inputhint)
|
||||
val input: EditText = itemView.findViewById(R.id.objective_input)
|
||||
val enterButton: Button = itemView.findViewById(R.id.objective_enterbutton)
|
||||
|
|
|
@ -104,7 +104,7 @@ object ObjectivesPlugin : PluginBase(PluginDescription()
|
|||
fun completeObjectives(activity: Activity, request: String) {
|
||||
val requestCode = SP.getString(R.string.key_objectives_request_code, "")
|
||||
var url = SP.getString(R.string.key_nsclientinternal_url, "").toLowerCase()
|
||||
if (!url.endsWith("\"")) url = "$url/"
|
||||
if (!url.endsWith("/")) url = "$url/"
|
||||
@Suppress("DEPRECATION") val hashNS = Hashing.sha1().hashString(url + BuildConfig.APPLICATION_ID + "/" + requestCode, Charsets.UTF_8).toString()
|
||||
if (request.equals(hashNS.substring(0, 10), ignoreCase = true)) {
|
||||
SP.putLong("Objectives_" + "openloop" + "_started", DateUtil.now())
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.dialogs
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import info.nightscout.androidaps.MainApp
|
||||
import info.nightscout.androidaps.R
|
||||
import info.nightscout.androidaps.logging.L
|
||||
import info.nightscout.androidaps.plugins.bus.RxBus.toObservable
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.events.EventNtpStatus
|
||||
import info.nightscout.androidaps.utils.FabricPrivacy
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.overview_bolusprogress_dialog.*
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class NtpProgressDialog : DialogFragment() {
|
||||
private val log = LoggerFactory.getLogger(L.UI)
|
||||
private val disposable = CompositeDisposable()
|
||||
|
||||
private val DEFAULT_STATE = MainApp.gs(R.string.timedetection)
|
||||
private var state: String = DEFAULT_STATE
|
||||
private var percent = 0
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?): View? {
|
||||
dialog?.setTitle(String.format(MainApp.gs(R.string.objectives)))
|
||||
isCancelable = false
|
||||
|
||||
state = savedInstanceState?.getString("state", DEFAULT_STATE) ?: DEFAULT_STATE
|
||||
percent = savedInstanceState?.getInt("percent", 0) ?: 0
|
||||
|
||||
return inflater.inflate(R.layout.overview_bolusprogress_dialog, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
overview_bolusprogress_stop.setOnClickListener { dismiss() }
|
||||
overview_bolusprogress_status.setText(state)
|
||||
overview_bolusprogress_progressbar.setMax(100)
|
||||
overview_bolusprogress_progressbar.setProgress(percent)
|
||||
overview_bolusprogress_stop.text = MainApp.gs(R.string.close)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (L.isEnabled(L.UI)) log.debug("onResume")
|
||||
if (percent == 100) {
|
||||
dismiss()
|
||||
return
|
||||
} else
|
||||
dialog?.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
|
||||
disposable.add(toObservable(EventNtpStatus::class.java)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({ event: EventNtpStatus ->
|
||||
if (L.isEnabled(L.UI)) log.debug("Status: " + event.status + " Percent: " + event.percent)
|
||||
overview_bolusprogress_status?.text = event.status
|
||||
overview_bolusprogress_progressbar?.progress = event.percent
|
||||
if (event.percent == 100) {
|
||||
SystemClock.sleep(100)
|
||||
dismiss()
|
||||
}
|
||||
state = event.status
|
||||
percent = event.percent
|
||||
}) { FabricPrivacy.logException(it) }
|
||||
)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
if (L.isEnabled(L.UI)) log.debug("onPause")
|
||||
super.onPause()
|
||||
disposable.clear()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
outState.putString("state", state)
|
||||
outState.putInt("percent", percent)
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package info.nightscout.androidaps.plugins.constraints.objectives.events
|
||||
|
||||
import info.nightscout.androidaps.events.Event
|
||||
|
||||
class EventNtpStatus(val status: String, val percent: Int) : Event()
|
|
@ -61,10 +61,6 @@ public abstract class Objective {
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean isRevertable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAccomplished() {
|
||||
return accomplishedOn != 0 && accomplishedOn < DateUtil.now();
|
||||
}
|
||||
|
@ -107,6 +103,8 @@ public abstract class Objective {
|
|||
return tasks;
|
||||
}
|
||||
|
||||
public boolean specialActionEnabled() { return true; }
|
||||
|
||||
public void specialAction(Activity activity, String input) {}
|
||||
|
||||
public abstract class Task {
|
||||
|
|
|
@ -7,6 +7,7 @@ import java.util.List;
|
|||
import info.nightscout.androidaps.MainApp;
|
||||
import info.nightscout.androidaps.R;
|
||||
import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin;
|
||||
import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin;
|
||||
import info.nightscout.androidaps.utils.SP;
|
||||
import info.nightscout.androidaps.utils.T;
|
||||
|
||||
|
@ -38,6 +39,11 @@ public class Objective3 extends Objective {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean specialActionEnabled() {
|
||||
return NSClientPlugin.getPlugin().nsClientService.isConnected && NSClientPlugin.getPlugin().nsClientService.hasWriteAuth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void specialAction(Activity activity, String input) {
|
||||
ObjectivesPlugin.INSTANCE.completeObjectives(activity, input);
|
||||
|
|
|
@ -25,9 +25,4 @@ public class Objective5 extends Objective {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRevertable() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,12 +16,16 @@ package info.nightscout.androidaps.utils;
|
|||
*/
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import info.nightscout.androidaps.logging.L;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
* <p>
|
||||
|
@ -35,7 +39,7 @@ import java.net.InetAddress;
|
|||
* </pre>
|
||||
*/
|
||||
public class SntpClient {
|
||||
private static final String TAG = "SntpClient";
|
||||
private static Logger log = LoggerFactory.getLogger(L.CORE);
|
||||
|
||||
//private static final int REFERENCE_TIME_OFFSET = 16;
|
||||
private static final int ORIGINATE_TIME_OFFSET = 24;
|
||||
|
@ -76,8 +80,10 @@ public class SntpClient {
|
|||
}
|
||||
|
||||
static void doNtpTime(final Callback callback) {
|
||||
log.debug("Time detection started");
|
||||
callback.success = requestTime("time.google.com", 5000);
|
||||
callback.time = getNtpTime() + SystemClock.elapsedRealtime() - getNtpTimeReference();
|
||||
log.debug("Time detection ended: " + callback.success + " " + DateUtil.dateAndTimeString(getNtpTime()));
|
||||
callback.run();
|
||||
}
|
||||
|
||||
|
@ -138,7 +144,7 @@ public class SntpClient {
|
|||
mNtpTimeReference = responseTicks;
|
||||
mRoundTripTime = roundTripTime;
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "request time failed: " + e);
|
||||
log.debug("request time failed: " + e);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,11 +68,18 @@
|
|||
android:text="@string/objectives_button_start" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/objective_back"
|
||||
android:id="@+id/objective_unfinish"
|
||||
style="@style/Widget.AppCompat.Button.Borderless.Colored"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/objectives_button_back" />
|
||||
android:text="@string/objectives_button_unfinish" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/objective_unstart"
|
||||
style="@style/Widget.AppCompat.Button.Borderless.Colored"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/objectives_button_unstart" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/objective_inputhint"
|
||||
|
|
|
@ -1637,6 +1637,10 @@
|
|||
<string name="format_carbs">%1$dg</string>
|
||||
<string name="common_on">On</string>
|
||||
<string name="common_off">Off</string>
|
||||
<string name="objectives_button_unfinish">Clear finished</string>
|
||||
<string name="objectives_button_unstart">Clear started</string>
|
||||
<string name="timedetection">Time detection</string>
|
||||
<string name="doyouwantresetstart">Do you want reset objective start? You may lose your progress.</string>
|
||||
<string name="nopumpselected">No pump selected</string>
|
||||
<string name="setupwizard_units_prompt">Select units you want to display values in</string>
|
||||
<string name="key_ns_uploadlocalprofile" translatable="false">ns_uploadlocalprofile</string>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.50'
|
||||
ext.kotlin_version = '1.3.61'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
|
|
Loading…
Reference in a new issue