mirror of
https://github.com/afollestad/nock-nock.git
synced 2025-08-09 01:18:39 +00:00
The ability to disable checks for sites, resolves #8.
This commit is contained in:
parent
ef73245831
commit
8193dd017d
12 changed files with 214 additions and 129 deletions
|
@ -46,7 +46,14 @@ class ServerVH constructor(
|
||||||
itemView.textStatus.setText(statusText)
|
itemView.textStatus.setText(statusText)
|
||||||
}
|
}
|
||||||
|
|
||||||
itemView.textInterval.text = model.intervalText()
|
if (model.disabled) {
|
||||||
|
itemView.textInterval.setText(R.string.checks_disabled)
|
||||||
|
} else {
|
||||||
|
itemView.textInterval.text = itemView.resources.getString(
|
||||||
|
R.string.next_check_x,
|
||||||
|
model.intervalText()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLongClick(view: View): Boolean {
|
override fun onLongClick(view: View): Boolean {
|
||||||
|
|
|
@ -55,7 +55,6 @@ import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.lang.System.currentTimeMillis
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.properties.Delegates.notNull
|
import kotlin.properties.Delegates.notNull
|
||||||
|
@ -233,7 +232,6 @@ class AddSiteActivity : AppCompatActivity(), View.OnClickListener {
|
||||||
|
|
||||||
newModel = newModel.copy(
|
newModel = newModel.copy(
|
||||||
checkInterval = selectedCheckInterval,
|
checkInterval = selectedCheckInterval,
|
||||||
lastCheck = currentTimeMillis() - selectedCheckInterval,
|
|
||||||
validationMode = selectedValidationMode,
|
validationMode = selectedValidationMode,
|
||||||
validationContent = selectedValidationMode.validationContent()
|
validationContent = selectedValidationMode.validationContent()
|
||||||
)
|
)
|
||||||
|
@ -242,8 +240,12 @@ class AddSiteActivity : AppCompatActivity(), View.OnClickListener {
|
||||||
launch(coroutineContext) {
|
launch(coroutineContext) {
|
||||||
loadingProgress.setLoading()
|
loadingProgress.setLoading()
|
||||||
val storedModel = async(IO) { serverModelStore.put(newModel) }.await()
|
val storedModel = async(IO) { serverModelStore.put(newModel) }.await()
|
||||||
checkStatusManager.cancelCheck(storedModel)
|
|
||||||
checkStatusManager.scheduleCheck(storedModel, rightNow = true)
|
checkStatusManager.scheduleCheck(
|
||||||
|
site = storedModel,
|
||||||
|
rightNow = true,
|
||||||
|
cancelPrevious = true
|
||||||
|
)
|
||||||
loadingProgress.setDone()
|
loadingProgress.setDone()
|
||||||
|
|
||||||
setResult(RESULT_OK)
|
setResult(RESULT_OK)
|
||||||
|
|
|
@ -131,6 +131,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
safeRegisterReceiver(intentReceiver, filter)
|
safeRegisterReceiver(intentReceiver, filter)
|
||||||
|
|
||||||
|
notificationManager.cancelStatusNotifications()
|
||||||
refreshModels()
|
refreshModels()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,10 +172,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
title(R.string.options)
|
title(R.string.options)
|
||||||
listItems(R.array.site_long_options) { _, i, _ ->
|
listItems(R.array.site_long_options) { _, i, _ ->
|
||||||
when (i) {
|
when (i) {
|
||||||
0 -> {
|
0 -> checkStatusManager.scheduleCheck(site = model, cancelPrevious = true)
|
||||||
checkStatusManager.cancelCheck(model)
|
|
||||||
checkStatusManager.scheduleCheck(model)
|
|
||||||
}
|
|
||||||
1 -> maybeRemoveSite(model) {
|
1 -> maybeRemoveSite(model) {
|
||||||
adapter.remove(i)
|
adapter.remove(i)
|
||||||
emptyText.showOrHide(adapter.itemCount == 0)
|
emptyText.showOrHide(adapter.itemCount == 0)
|
||||||
|
@ -207,7 +205,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
)
|
)
|
||||||
positiveButton(R.string.remove) {
|
positiveButton(R.string.remove) {
|
||||||
checkStatusManager.cancelCheck(model)
|
checkStatusManager.cancelCheck(model)
|
||||||
notificationManager.cancelStatusNotifications()
|
notificationManager.cancelStatusNotification(model)
|
||||||
performRemoveSite(model, onRemoved)
|
performRemoveSite(model, onRemoved)
|
||||||
}
|
}
|
||||||
negativeButton(android.R.string.cancel)
|
negativeButton(android.R.string.cancel)
|
||||||
|
|
|
@ -21,6 +21,7 @@ import androidx.annotation.CheckResult
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
|
import androidx.core.text.HtmlCompat.FROM_HTML_MODE_LEGACY
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.nocknock.BuildConfig
|
import com.afollestad.nocknock.BuildConfig
|
||||||
import com.afollestad.nocknock.R
|
import com.afollestad.nocknock.R
|
||||||
|
@ -74,7 +75,6 @@ import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.lang.System.currentTimeMillis
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
private const val KEY_VIEW_MODEL = "site_model"
|
private const val KEY_VIEW_MODEL = "site_model"
|
||||||
|
@ -228,7 +228,15 @@ class ViewSiteActivity : AppCompatActivity(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
disableChecksButton.setOnClickListener(this@ViewSiteActivity)
|
||||||
|
disableChecksButton.showOrHide(!this.disabled)
|
||||||
|
|
||||||
doneBtn.setOnClickListener(this@ViewSiteActivity)
|
doneBtn.setOnClickListener(this@ViewSiteActivity)
|
||||||
|
doneBtn.setText(
|
||||||
|
if (this.disabled) R.string.renable_and_save_changes
|
||||||
|
else R.string.save_changes
|
||||||
|
)
|
||||||
|
|
||||||
invalidateMenuForStatus()
|
invalidateMenuForStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,11 +253,139 @@ class ViewSiteActivity : AppCompatActivity(),
|
||||||
safeUnregisterReceiver(intentReceiver)
|
safeUnregisterReceiver(intentReceiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onClick(view: View) = when (view.id) {
|
||||||
|
R.id.doneBtn -> performSaveChangesAndFinish()
|
||||||
|
R.id.disableChecksButton -> maybeDisableChecks()
|
||||||
|
else -> Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMenuItemClick(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.refresh -> performCheckNow()
|
||||||
|
R.id.remove -> maybeRemoveSite()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun performCheckNow() {
|
||||||
|
rootView.scopeWhileAttached(Main) {
|
||||||
|
launch(coroutineContext) {
|
||||||
|
disableChecksButton.disable()
|
||||||
|
loadingProgress.setLoading()
|
||||||
|
updateModelFromInput(false)
|
||||||
|
currentModel = currentModel.copy(status = WAITING)
|
||||||
|
displayCurrentModel()
|
||||||
|
|
||||||
|
async(IO) { serverModelStore.update(currentModel) }.await()
|
||||||
|
|
||||||
|
checkStatusManager.scheduleCheck(
|
||||||
|
site = currentModel,
|
||||||
|
rightNow = true,
|
||||||
|
cancelPrevious = true
|
||||||
|
)
|
||||||
|
loadingProgress.setDone()
|
||||||
|
disableChecksButton.enable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun maybeRemoveSite() {
|
||||||
|
MaterialDialog(this).show {
|
||||||
|
title(R.string.remove_site)
|
||||||
|
message(
|
||||||
|
text = HtmlCompat.fromHtml(
|
||||||
|
context.getString(R.string.remove_site_prompt, currentModel.name),
|
||||||
|
FROM_HTML_MODE_LEGACY
|
||||||
|
)
|
||||||
|
)
|
||||||
|
positiveButton(R.string.remove) {
|
||||||
|
checkStatusManager.cancelCheck(currentModel)
|
||||||
|
notificationManager.cancelStatusNotification(currentModel)
|
||||||
|
performRemoveSite()
|
||||||
|
}
|
||||||
|
negativeButton(android.R.string.cancel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun performRemoveSite() {
|
||||||
|
rootView.scopeWhileAttached(Main) {
|
||||||
|
launch(coroutineContext) {
|
||||||
|
loadingProgress.setLoading()
|
||||||
|
async(IO) { serverModelStore.delete(currentModel) }.await()
|
||||||
|
loadingProgress.setDone()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun maybeDisableChecks() {
|
||||||
|
MaterialDialog(this).show {
|
||||||
|
title(R.string.disable_automatic_checks)
|
||||||
|
message(
|
||||||
|
text = HtmlCompat.fromHtml(
|
||||||
|
context.getString(R.string.disable_automatic_checks_prompt, currentModel.name),
|
||||||
|
FROM_HTML_MODE_LEGACY
|
||||||
|
)
|
||||||
|
)
|
||||||
|
positiveButton(R.string.disable) {
|
||||||
|
checkStatusManager.cancelCheck(currentModel)
|
||||||
|
notificationManager.cancelStatusNotification(currentModel)
|
||||||
|
performDisableChecks()
|
||||||
|
}
|
||||||
|
negativeButton(android.R.string.cancel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun performDisableChecks() {
|
||||||
|
rootView.scopeWhileAttached(Main) {
|
||||||
|
launch(coroutineContext) {
|
||||||
|
loadingProgress.setLoading()
|
||||||
|
currentModel = currentModel.copy(
|
||||||
|
disabled = true,
|
||||||
|
lastCheck = LAST_CHECK_NONE
|
||||||
|
)
|
||||||
|
async(IO) { serverModelStore.update(currentModel) }.await()
|
||||||
|
loadingProgress.setDone()
|
||||||
|
displayCurrentModel() // invalidate UI to reflect disabled state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun performSaveChangesAndFinish() {
|
||||||
|
rootView.scopeWhileAttached(Main) {
|
||||||
|
launch(coroutineContext) {
|
||||||
|
loadingProgress.setLoading()
|
||||||
|
if (!updateModelFromInput(true)) {
|
||||||
|
// Validation didn't pass
|
||||||
|
loadingProgress.setDone()
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
|
||||||
|
async(IO) { serverModelStore.update(currentModel) }.await()
|
||||||
|
checkStatusManager.scheduleCheck(
|
||||||
|
site = currentModel,
|
||||||
|
rightNow = true,
|
||||||
|
cancelPrevious = true
|
||||||
|
)
|
||||||
|
|
||||||
|
loadingProgress.setDone()
|
||||||
|
setResult(RESULT_OK)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun invalidateMenuForStatus() {
|
||||||
|
val item = toolbar.menu.findItem(R.id.refresh)
|
||||||
|
item.isEnabled = currentModel.status != CHECKING && currentModel.status != WAITING
|
||||||
|
}
|
||||||
|
|
||||||
@CheckResult private fun updateModelFromInput(withValidation: Boolean): Boolean {
|
@CheckResult private fun updateModelFromInput(withValidation: Boolean): Boolean {
|
||||||
currentModel = currentModel.copy(
|
currentModel = currentModel.copy(
|
||||||
name = inputName.trimmedText(),
|
name = inputName.trimmedText(),
|
||||||
url = inputUrl.trimmedText(),
|
url = inputUrl.trimmedText(),
|
||||||
status = WAITING
|
status = WAITING,
|
||||||
|
disabled = false
|
||||||
)
|
)
|
||||||
|
|
||||||
if (withValidation && currentModel.name.isEmpty()) {
|
if (withValidation && currentModel.name.isEmpty()) {
|
||||||
|
@ -281,7 +417,6 @@ class ViewSiteActivity : AppCompatActivity(),
|
||||||
|
|
||||||
currentModel = currentModel.copy(
|
currentModel = currentModel.copy(
|
||||||
checkInterval = selectedCheckInterval,
|
checkInterval = selectedCheckInterval,
|
||||||
lastCheck = currentTimeMillis() - selectedCheckInterval,
|
|
||||||
validationMode = selectedValidationMode,
|
validationMode = selectedValidationMode,
|
||||||
validationContent = selectedValidationMode.validationContent()
|
validationContent = selectedValidationMode.validationContent()
|
||||||
)
|
)
|
||||||
|
@ -289,91 +424,6 @@ class ViewSiteActivity : AppCompatActivity(),
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save button
|
|
||||||
override fun onClick(view: View) {
|
|
||||||
rootView.scopeWhileAttached(Main) {
|
|
||||||
launch(coroutineContext) {
|
|
||||||
loadingProgress.setLoading()
|
|
||||||
if (!updateModelFromInput(true)) {
|
|
||||||
// Validation didn't pass
|
|
||||||
loadingProgress.setDone()
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
|
|
||||||
async(IO) { serverModelStore.update(currentModel) }.await()
|
|
||||||
checkStatusManager.cancelCheck(currentModel)
|
|
||||||
checkStatusManager.scheduleCheck(currentModel, rightNow = true)
|
|
||||||
|
|
||||||
loadingProgress.setDone()
|
|
||||||
setResult(RESULT_OK)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMenuItemClick(item: MenuItem): Boolean {
|
|
||||||
when (item.itemId) {
|
|
||||||
R.id.refresh -> {
|
|
||||||
rootView.scopeWhileAttached(Main) {
|
|
||||||
launch(coroutineContext) {
|
|
||||||
disableChecksButton.disable()
|
|
||||||
loadingProgress.setLoading()
|
|
||||||
updateModelFromInput(false)
|
|
||||||
currentModel = currentModel.copy(status = WAITING)
|
|
||||||
displayCurrentModel()
|
|
||||||
|
|
||||||
async(IO) { serverModelStore.update(currentModel) }.await()
|
|
||||||
|
|
||||||
checkStatusManager.cancelCheck(currentModel)
|
|
||||||
checkStatusManager.scheduleCheck(currentModel, rightNow = true)
|
|
||||||
loadingProgress.setDone()
|
|
||||||
disableChecksButton.enable()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
R.id.remove -> {
|
|
||||||
maybeRemoveSite(currentModel)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun maybeRemoveSite(model: ServerModel) {
|
|
||||||
MaterialDialog(this).show {
|
|
||||||
title(R.string.remove_site)
|
|
||||||
message(
|
|
||||||
text = HtmlCompat.fromHtml(
|
|
||||||
context.getString(R.string.remove_site_prompt, model.name),
|
|
||||||
HtmlCompat.FROM_HTML_MODE_LEGACY
|
|
||||||
)
|
|
||||||
)
|
|
||||||
positiveButton(R.string.remove) {
|
|
||||||
checkStatusManager.cancelCheck(model)
|
|
||||||
notificationManager.cancelStatusNotifications()
|
|
||||||
performRemoveSite(model)
|
|
||||||
}
|
|
||||||
negativeButton(android.R.string.cancel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun performRemoveSite(model: ServerModel) {
|
|
||||||
rootView.scopeWhileAttached(Main) {
|
|
||||||
launch(coroutineContext) {
|
|
||||||
loadingProgress.setLoading()
|
|
||||||
async(IO) { serverModelStore.delete(model) }.await()
|
|
||||||
loadingProgress.setDone()
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun invalidateMenuForStatus() {
|
|
||||||
val item = toolbar.menu.findItem(R.id.refresh)
|
|
||||||
item.isEnabled = currentModel.status != CHECKING && currentModel.status != WAITING
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ValidationMode.validationContent() = when (this) {
|
private fun ValidationMode.validationContent() = when (this) {
|
||||||
STATUS_CODE -> null
|
STATUS_CODE -> null
|
||||||
TERM_SEARCH -> responseValidationSearchTerm.trimmedText()
|
TERM_SEARCH -> responseValidationSearchTerm.trimmedText()
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:fontFamily="@font/lato_light"
|
android:fontFamily="@font/lato_black"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:textColor="?android:textColorSecondary"
|
android:textColor="?android:textColorSecondary"
|
||||||
android:textSize="@dimen/caption_font_size"
|
android:textSize="@dimen/caption_font_size"
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/list_text_spacing"
|
android:layout_marginTop="@dimen/list_text_spacing"
|
||||||
android:fontFamily="@font/lato"
|
android:fontFamily="@font/lato_light"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:textColor="?android:textColorSecondary"
|
android:textColor="?android:textColorSecondary"
|
||||||
android:textSize="@dimen/body_font_size"
|
android:textSize="@dimen/body_font_size"
|
||||||
|
|
|
@ -30,13 +30,22 @@
|
||||||
<string name="remove_site_prompt"><![CDATA[Remove <b>%1$s</b> from your sites?]]></string>
|
<string name="remove_site_prompt"><![CDATA[Remove <b>%1$s</b> from your sites?]]></string>
|
||||||
<string name="remove">Remove</string>
|
<string name="remove">Remove</string>
|
||||||
<string name="save_changes">Save Changes</string>
|
<string name="save_changes">Save Changes</string>
|
||||||
<string name="disable_automatic_checks">Disable Automatic Checks</string>
|
|
||||||
<string name="view_site">View Site</string>
|
<string name="view_site">View Site</string>
|
||||||
<string name="last_check_result">Last Check Result</string>
|
<string name="last_check_result">Last Check Result</string>
|
||||||
<string name="next_check">Next Check</string>
|
<string name="next_check">Next Check</string>
|
||||||
|
<string name="next_check_x">Next Check: %1$s</string>
|
||||||
<string name="none_turned_off">None (turned off)</string>
|
<string name="none_turned_off">None (turned off)</string>
|
||||||
<string name="none">None</string>
|
<string name="none">None</string>
|
||||||
|
|
||||||
|
<string name="disable_automatic_checks">Disable Automatic Checks</string>
|
||||||
|
<string name="disable_automatic_checks_prompt"><![CDATA[
|
||||||
|
Disable automatic checks for <b>%1$s</b>? The site will not be validated in the background
|
||||||
|
until you re-enable checks for it. You can still manually perform checks by tapping the
|
||||||
|
Refresh icon at the top of this page.
|
||||||
|
]]></string>
|
||||||
|
<string name="disable">Disable</string>
|
||||||
|
<string name="renable_and_save_changes">Enable Checks & Save Changes</string>
|
||||||
|
|
||||||
<string name="refresh_status">Refresh Status</string>
|
<string name="refresh_status">Refresh Status</string>
|
||||||
|
|
||||||
<string name="warning_http_url">
|
<string name="warning_http_url">
|
||||||
|
|
|
@ -11,6 +11,7 @@ import com.afollestad.nocknock.data.ServerStatus.OK
|
||||||
import com.afollestad.nocknock.utilities.ext.timeString
|
import com.afollestad.nocknock.utilities.ext.timeString
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.lang.System.currentTimeMillis
|
import java.lang.System.currentTimeMillis
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
const val CHECK_INTERVAL_UNSET = -1L
|
const val CHECK_INTERVAL_UNSET = -1L
|
||||||
const val LAST_CHECK_NONE = -1L
|
const val LAST_CHECK_NONE = -1L
|
||||||
|
@ -62,12 +63,10 @@ data class ServerModel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun intervalText() = if (checkInterval <= 0) {
|
fun intervalText(): String {
|
||||||
""
|
|
||||||
} else {
|
|
||||||
val now = currentTimeMillis()
|
val now = currentTimeMillis()
|
||||||
val nextCheck = lastCheck + checkInterval
|
val nextCheck = max(lastCheck, 0) + checkInterval
|
||||||
(nextCheck - now).timeString()
|
return (nextCheck - now).timeString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun toContentValues() = ContentValues().apply {
|
fun toContentValues() = ContentValues().apply {
|
||||||
|
|
|
@ -36,3 +36,5 @@ fun ServerStatus.textRes() = when (this) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Int.toServerStatus() = ServerStatus.fromValue(this)
|
fun Int.toServerStatus() = ServerStatus.fromValue(this)
|
||||||
|
|
||||||
|
fun ServerStatus.isPending() = this == WAITING || this == CHECKING
|
||||||
|
|
|
@ -17,6 +17,7 @@ import com.afollestad.nocknock.data.ServerStatus.OK
|
||||||
import com.afollestad.nocknock.data.ValidationMode.JAVASCRIPT
|
import com.afollestad.nocknock.data.ValidationMode.JAVASCRIPT
|
||||||
import com.afollestad.nocknock.data.ValidationMode.STATUS_CODE
|
import com.afollestad.nocknock.data.ValidationMode.STATUS_CODE
|
||||||
import com.afollestad.nocknock.data.ValidationMode.TERM_SEARCH
|
import com.afollestad.nocknock.data.ValidationMode.TERM_SEARCH
|
||||||
|
import com.afollestad.nocknock.data.isPending
|
||||||
import com.afollestad.nocknock.engine.BuildConfig.APPLICATION_ID
|
import com.afollestad.nocknock.engine.BuildConfig.APPLICATION_ID
|
||||||
import com.afollestad.nocknock.engine.db.ServerModelStore
|
import com.afollestad.nocknock.engine.db.ServerModelStore
|
||||||
import com.afollestad.nocknock.notifications.NockNotificationManager
|
import com.afollestad.nocknock.notifications.NockNotificationManager
|
||||||
|
@ -127,7 +128,10 @@ class CheckStatusJob : JobService() {
|
||||||
notificationManager.postStatusNotification(result)
|
notificationManager.postStatusNotification(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkStatusManager.scheduleCheck(result)
|
checkStatusManager.scheduleCheck(
|
||||||
|
site = result,
|
||||||
|
fromFinishingJob = true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -146,8 +150,8 @@ class CheckStatusJob : JobService() {
|
||||||
log("Updating ${site.name} (${site.url}) status to $status...")
|
log("Updating ${site.name} (${site.url}) status to $status...")
|
||||||
|
|
||||||
val lastCheckTime =
|
val lastCheckTime =
|
||||||
if (status == CHECKING) currentTimeMillis()
|
if (status.isPending()) site.lastCheck
|
||||||
else site.lastCheck
|
else currentTimeMillis()
|
||||||
val reason =
|
val reason =
|
||||||
if (status == OK) null
|
if (status == OK) null
|
||||||
else site.reason
|
else site.reason
|
||||||
|
|
|
@ -38,7 +38,9 @@ interface CheckStatusManager {
|
||||||
|
|
||||||
fun scheduleCheck(
|
fun scheduleCheck(
|
||||||
site: ServerModel,
|
site: ServerModel,
|
||||||
rightNow: Boolean = false
|
rightNow: Boolean = false,
|
||||||
|
cancelPrevious: Boolean = false,
|
||||||
|
fromFinishingJob: Boolean = false
|
||||||
)
|
)
|
||||||
|
|
||||||
fun cancelCheck(site: ServerModel)
|
fun cancelCheck(site: ServerModel)
|
||||||
|
@ -55,7 +57,6 @@ class RealCheckStatusManager @Inject constructor(
|
||||||
) : CheckStatusManager {
|
) : CheckStatusManager {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private fun log(message: String) {
|
private fun log(message: String) {
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
Log.d("CheckStatusManager", message)
|
Log.d("CheckStatusManager", message)
|
||||||
|
@ -68,14 +69,13 @@ class RealCheckStatusManager @Inject constructor(
|
||||||
if (sites.isEmpty()) {
|
if (sites.isEmpty()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log("Ensuring sites have scheduled checks.")
|
log("Ensuring enabled sites have scheduled checks.")
|
||||||
|
sites.filter { !it.disabled }
|
||||||
sites.forEach { site ->
|
.forEach { site ->
|
||||||
val existingJob = jobScheduler.allPendingJobs
|
val existingJob = jobForSite(site)
|
||||||
.firstOrNull { job -> job.id == site.id }
|
|
||||||
if (existingJob == null) {
|
if (existingJob == null) {
|
||||||
log("Site ${site.id} does NOT have a scheduled job, running one now.")
|
log("Site ${site.id} does NOT have a scheduled job, running one now.")
|
||||||
scheduleCheck(site, rightNow = true)
|
scheduleCheck(site = site, rightNow = true)
|
||||||
} else {
|
} else {
|
||||||
log("Site ${site.id} already has a scheduled job. Nothing to do.")
|
log("Site ${site.id} already has a scheduled job. Nothing to do.")
|
||||||
}
|
}
|
||||||
|
@ -84,18 +84,28 @@ class RealCheckStatusManager @Inject constructor(
|
||||||
|
|
||||||
override fun scheduleCheck(
|
override fun scheduleCheck(
|
||||||
site: ServerModel,
|
site: ServerModel,
|
||||||
rightNow: Boolean
|
rightNow: Boolean,
|
||||||
|
cancelPrevious: Boolean,
|
||||||
|
fromFinishingJob: Boolean
|
||||||
) {
|
) {
|
||||||
check(site.id != 0) { "Cannot schedule checks for jobs with no ID." }
|
check(site.id != 0) { "Cannot schedule checks for jobs with no ID." }
|
||||||
log("Requesting a check job for site to be scheduled: $site")
|
if (cancelPrevious) {
|
||||||
|
cancelCheck(site)
|
||||||
|
} else if (!fromFinishingJob) {
|
||||||
|
val existingJob = jobForSite(site)
|
||||||
|
check(existingJob == null) {
|
||||||
|
"Site ${site.id} already has a scheduled job, and cancelPrevious = false."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log("Requesting a check job for site to be scheduled: $site")
|
||||||
val extras = PersistableBundle().apply {
|
val extras = PersistableBundle().apply {
|
||||||
putInt(KEY_SITE_ID, site.id)
|
putInt(KEY_SITE_ID, site.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that we don't use the periodic feature of JobScheduler because it requires a
|
// Note: we don't use the periodic feature of JobScheduler because it requires a
|
||||||
// minimum of 15 minutes between each execution which may not be what's requested by the
|
// minimum of 15 minutes between each execution which may not be what's requested by the
|
||||||
// user of this app.
|
// user of the app.
|
||||||
val jobInfo = jobInfo(app, site.id, CheckStatusJob::class.java) {
|
val jobInfo = jobInfo(app, site.id, CheckStatusJob::class.java) {
|
||||||
setRequiredNetworkType(NETWORK_TYPE_ANY)
|
setRequiredNetworkType(NETWORK_TYPE_ANY)
|
||||||
if (rightNow) {
|
if (rightNow) {
|
||||||
|
@ -163,4 +173,8 @@ class RealCheckStatusManager @Inject constructor(
|
||||||
CheckResult(model = site.copy(status = ERROR, reason = ex.message))
|
CheckResult(model = site.copy(status = ERROR, reason = ex.message))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun jobForSite(site: ServerModel) =
|
||||||
|
jobScheduler.allPendingJobs
|
||||||
|
.firstOrNull { job -> job.id == site.id }
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ const val WEEK = DAY * 7
|
||||||
const val MONTH = WEEK * 4
|
const val MONTH = WEEK * 4
|
||||||
|
|
||||||
fun Long.timeString() = when {
|
fun Long.timeString() = when {
|
||||||
this <= 0 -> ""
|
this <= 0 -> "??"
|
||||||
this >= MONTH ->
|
this >= MONTH ->
|
||||||
"${ceil((this.toFloat() / MONTH.toFloat()).toDouble()).toInt()}mo"
|
"${ceil((this.toFloat() / MONTH.toFloat()).toDouble()).toInt()}mo"
|
||||||
this >= WEEK ->
|
this >= WEEK ->
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">utilities</string>
|
<string name="checks_disabled">Checks Disabled</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue