diff --git a/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSiteActivity.kt b/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSiteActivity.kt
index 65e71c8..ab9f933 100644
--- a/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSiteActivity.kt
+++ b/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSiteActivity.kt
@@ -22,12 +22,14 @@ import com.afollestad.nocknock.viewcomponents.ext.conceal
import com.afollestad.nocknock.viewcomponents.ext.onItemSelected
import com.afollestad.nocknock.viewcomponents.ext.onLayout
import com.afollestad.nocknock.viewcomponents.ext.showOrHide
+import com.afollestad.nocknock.viewcomponents.ext.textAsInt
import com.afollestad.nocknock.viewcomponents.ext.trimmedText
import kotlinx.android.synthetic.main.activity_addsite.checkIntervalLayout
import kotlinx.android.synthetic.main.activity_addsite.doneBtn
import kotlinx.android.synthetic.main.activity_addsite.inputName
import kotlinx.android.synthetic.main.activity_addsite.inputUrl
import kotlinx.android.synthetic.main.activity_addsite.loadingProgress
+import kotlinx.android.synthetic.main.activity_addsite.responseTimeoutInput
import kotlinx.android.synthetic.main.activity_addsite.responseValidationMode
import kotlinx.android.synthetic.main.activity_addsite.responseValidationSearchTerm
import kotlinx.android.synthetic.main.activity_addsite.rootView
@@ -99,6 +101,7 @@ class AddSiteActivity : AppCompatActivity(), AddSiteView {
val checkInterval = checkIntervalLayout.getSelectedCheckInterval()
val validationMode =
responseValidationMode.selectedItemPosition.indexToValidationMode()
+ val defaultTimeout = getString(R.string.response_timeout_default).toInt()
isClosing = true
presenter.commit(
@@ -106,7 +109,8 @@ class AddSiteActivity : AppCompatActivity(), AddSiteView {
url = inputUrl.trimmedText(),
checkInterval = checkInterval,
validationMode = validationMode,
- validationContent = validationMode.validationContent()
+ validationContent = validationMode.validationContent(),
+ networkTimeout = responseTimeoutInput.textAsInt(defaultValue = defaultTimeout)
)
}
}
@@ -165,6 +169,11 @@ class AddSiteActivity : AppCompatActivity(), AddSiteView {
null
}
)
+ responseTimeoutInput.error = if (errors.networkTimeout != null) {
+ getString(errors.networkTimeout!!)
+ } else {
+ null
+ }
}
override fun onSiteAdded() {
diff --git a/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSitePresenter.kt b/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSitePresenter.kt
index 61e1b7e..e95d379 100644
--- a/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSitePresenter.kt
+++ b/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSitePresenter.kt
@@ -27,11 +27,12 @@ data class InputErrors(
var url: Int? = null,
var checkInterval: Int? = null,
var termSearch: Int? = null,
- var javaScript: Int? = null
+ var javaScript: Int? = null,
+ var networkTimeout: Int? = null
) {
@CheckResult fun any(): Boolean {
return name != null || url != null || checkInterval != null ||
- termSearch != null || javaScript != null
+ termSearch != null || javaScript != null || networkTimeout != null
}
}
@@ -52,7 +53,8 @@ interface AddSitePresenter {
url: String,
checkInterval: Long,
validationMode: ValidationMode,
- validationContent: String?
+ validationContent: String?,
+ networkTimeout: Int
)
fun dropView()
@@ -106,7 +108,8 @@ class RealAddSitePresenter @Inject constructor(
url: String,
checkInterval: Long,
validationMode: ValidationMode,
- validationContent: String?
+ validationContent: String?,
+ networkTimeout: Int
) {
val inputErrors = InputErrors()
@@ -126,6 +129,9 @@ class RealAddSitePresenter @Inject constructor(
} else if (validationMode == JAVASCRIPT && validationContent.isNullOrEmpty()) {
inputErrors.javaScript = R.string.please_enter_javaScript
}
+ if (networkTimeout <= 0) {
+ inputErrors.networkTimeout = R.string.please_enter_networkTimeout
+ }
if (inputErrors.any()) {
view?.setInputErrors(inputErrors)
@@ -138,7 +144,8 @@ class RealAddSitePresenter @Inject constructor(
status = WAITING,
checkInterval = checkInterval,
validationMode = validationMode,
- validationContent = validationContent
+ validationContent = validationContent,
+ networkTimeout = networkTimeout
)
with(view!!) {
diff --git a/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteActivity.kt b/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteActivity.kt
index 59d2a69..c44510f 100644
--- a/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteActivity.kt
+++ b/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteActivity.kt
@@ -33,6 +33,7 @@ import com.afollestad.nocknock.viewcomponents.ext.dimenFloat
import com.afollestad.nocknock.viewcomponents.ext.onItemSelected
import com.afollestad.nocknock.viewcomponents.ext.onScroll
import com.afollestad.nocknock.viewcomponents.ext.showOrHide
+import com.afollestad.nocknock.viewcomponents.ext.textAsInt
import com.afollestad.nocknock.viewcomponents.ext.trimmedText
import kotlinx.android.synthetic.main.activity_viewsite.checkIntervalLayout
import kotlinx.android.synthetic.main.activity_viewsite.disableChecksButton
@@ -41,6 +42,7 @@ import kotlinx.android.synthetic.main.activity_viewsite.iconStatus
import kotlinx.android.synthetic.main.activity_viewsite.inputName
import kotlinx.android.synthetic.main.activity_viewsite.inputUrl
import kotlinx.android.synthetic.main.activity_viewsite.loadingProgress
+import kotlinx.android.synthetic.main.activity_viewsite.responseTimeoutInput
import kotlinx.android.synthetic.main.activity_viewsite.responseValidationMode
import kotlinx.android.synthetic.main.activity_viewsite.responseValidationSearchTerm
import kotlinx.android.synthetic.main.activity_viewsite.rootView
@@ -113,13 +115,15 @@ class ViewSiteActivity : AppCompatActivity(), ViewSiteView {
val checkInterval = checkIntervalLayout.getSelectedCheckInterval()
val validationMode =
responseValidationMode.selectedItemPosition.indexToValidationMode()
+ val defaultTimeout = getString(R.string.response_timeout_default).toInt()
presenter.commit(
name = inputName.trimmedText(),
url = inputUrl.trimmedText(),
checkInterval = checkInterval,
validationMode = validationMode,
- validationContent = validationMode.validationContent()
+ validationContent = validationMode.validationContent(),
+ networkTimeout = responseTimeoutInput.textAsInt(defaultValue = defaultTimeout)
)
}
@@ -189,6 +193,8 @@ class ViewSiteActivity : AppCompatActivity(), ViewSiteView {
}
}
+ responseTimeoutInput.setText(model.networkTimeout.toString())
+
disableChecksButton.showOrHide(!this.disabled)
doneBtn.setText(
if (this.disabled) R.string.renable_and_save_changes
@@ -228,6 +234,11 @@ class ViewSiteActivity : AppCompatActivity(), ViewSiteView {
null
}
)
+ responseTimeoutInput.error = if (errors.networkTimeout != null) {
+ getString(errors.networkTimeout!!)
+ } else {
+ null
+ }
}
override fun scopeWhileAttached(
diff --git a/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSitePresenter.kt b/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSitePresenter.kt
index 376b3c0..0241979 100644
--- a/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSitePresenter.kt
+++ b/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSitePresenter.kt
@@ -34,11 +34,12 @@ data class InputErrors(
var url: Int? = null,
var checkInterval: Int? = null,
var termSearch: Int? = null,
- var javaScript: Int? = null
+ var javaScript: Int? = null,
+ var networkTimeout: Int? = null
) {
@CheckResult fun any(): Boolean {
return name != null || url != null || checkInterval != null ||
- termSearch != null || javaScript != null
+ termSearch != null || javaScript != null || networkTimeout != null
}
}
@@ -66,7 +67,8 @@ interface ViewSitePresenter {
url: String,
checkInterval: Long,
validationMode: ValidationMode,
- validationContent: String?
+ validationContent: String?,
+ networkTimeout: Int
)
fun checkNow()
@@ -151,7 +153,8 @@ class RealViewSitePresenter @Inject constructor(
url: String,
checkInterval: Long,
validationMode: ValidationMode,
- validationContent: String?
+ validationContent: String?,
+ networkTimeout: Int
) {
val inputErrors = InputErrors()
@@ -171,6 +174,9 @@ class RealViewSitePresenter @Inject constructor(
} else if (validationMode == JAVASCRIPT && validationContent.isNullOrEmpty()) {
inputErrors.javaScript = R.string.please_enter_javaScript
}
+ if (networkTimeout <= 0) {
+ inputErrors.networkTimeout = R.string.please_enter_networkTimeout
+ }
if (inputErrors.any()) {
view?.setInputErrors(inputErrors)
@@ -184,7 +190,8 @@ class RealViewSitePresenter @Inject constructor(
checkInterval = checkInterval,
validationMode = validationMode,
validationContent = validationContent,
- disabled = false
+ disabled = false,
+ networkTimeout = networkTimeout
)
with(view!!) {
diff --git a/app/src/main/res/layout/activity_addsite.xml b/app/src/main/res/layout/activity_addsite.xml
index 90298cb..c19fba1 100644
--- a/app/src/main/res/layout/activity_addsite.xml
+++ b/app/src/main/res/layout/activity_addsite.xml
@@ -100,6 +100,28 @@
android:layout_marginTop="@dimen/content_inset"
/>
+
+
+
+
+
+
+
+
Please input a check interval.
Please input a search term.
Please input a validation script.
+ Please enter a network timeout greater than 0.
Options
Already checking sites!
@@ -49,6 +50,9 @@
Disable
Enable Checks & Save Changes
+ Network Response Timeout
+ 10000
+
Refresh Status
diff --git a/app/src/test/java/com/afollestad/nocknock/AddSitePresenterTest.kt b/app/src/test/java/com/afollestad/nocknock/AddSitePresenterTest.kt
index 692c5ca..d1941eb 100644
--- a/app/src/test/java/com/afollestad/nocknock/AddSitePresenterTest.kt
+++ b/app/src/test/java/com/afollestad/nocknock/AddSitePresenterTest.kt
@@ -113,7 +113,8 @@ class AddSitePresenterTest {
"https://test.com",
1,
STATUS_CODE,
- null
+ null,
+ 60000
)
val inputErrorsCaptor = argumentCaptor()
@@ -131,7 +132,8 @@ class AddSitePresenterTest {
"",
1,
STATUS_CODE,
- null
+ null,
+ 60000
)
val inputErrorsCaptor = argumentCaptor()
@@ -149,7 +151,8 @@ class AddSitePresenterTest {
"ftp://hello.com",
1,
STATUS_CODE,
- null
+ null,
+ 60000
)
val inputErrorsCaptor = argumentCaptor()
@@ -167,7 +170,8 @@ class AddSitePresenterTest {
"https://hello.com",
-1,
STATUS_CODE,
- null
+ null,
+ 60000
)
val inputErrorsCaptor = argumentCaptor()
@@ -185,7 +189,8 @@ class AddSitePresenterTest {
"https://hello.com",
1,
TERM_SEARCH,
- null
+ null,
+ 60000
)
val inputErrorsCaptor = argumentCaptor()
@@ -197,13 +202,33 @@ class AddSitePresenterTest {
assertThat(errors.termSearch).isEqualTo(R.string.please_enter_search_term)
}
+ @Test fun commit_networkTimeout_error() {
+ presenter.commit(
+ "Testing",
+ "https://hello.com",
+ 1,
+ STATUS_CODE,
+ null,
+ 0
+ )
+
+ val inputErrorsCaptor = argumentCaptor()
+ verify(view).setInputErrors(inputErrorsCaptor.capture())
+ verify(checkStatusManager, never())
+ .scheduleCheck(any(), any(), any(), any())
+
+ val errors = inputErrorsCaptor.firstValue
+ assertThat(errors.networkTimeout).isEqualTo(R.string.please_enter_networkTimeout)
+ }
+
@Test fun commit_javaScript_error() {
presenter.commit(
"Testing",
"https://hello.com",
1,
JAVASCRIPT,
- null
+ null,
+ 60000
)
val inputErrorsCaptor = argumentCaptor()
@@ -221,7 +246,8 @@ class AddSitePresenterTest {
"https://hello.com",
1,
STATUS_CODE,
- null
+ null,
+ 60000
)
val modelCaptor = argumentCaptor()
diff --git a/app/src/test/java/com/afollestad/nocknock/ViewSitePresenterTest.kt b/app/src/test/java/com/afollestad/nocknock/ViewSitePresenterTest.kt
index d938966..eb7b7f8 100644
--- a/app/src/test/java/com/afollestad/nocknock/ViewSitePresenterTest.kt
+++ b/app/src/test/java/com/afollestad/nocknock/ViewSitePresenterTest.kt
@@ -156,7 +156,8 @@ class ViewSitePresenterTest {
"https://test.com",
1,
STATUS_CODE,
- null
+ null,
+ 60000
)
val inputErrorsCaptor = argumentCaptor()
@@ -174,7 +175,8 @@ class ViewSitePresenterTest {
"",
1,
STATUS_CODE,
- null
+ null,
+ 60000
)
val inputErrorsCaptor = argumentCaptor()
@@ -192,7 +194,8 @@ class ViewSitePresenterTest {
"ftp://hello.com",
1,
STATUS_CODE,
- null
+ null,
+ 60000
)
val inputErrorsCaptor = argumentCaptor()
@@ -210,7 +213,8 @@ class ViewSitePresenterTest {
"https://hello.com",
-1,
STATUS_CODE,
- null
+ null,
+ 60000
)
val inputErrorsCaptor = argumentCaptor()
@@ -228,7 +232,8 @@ class ViewSitePresenterTest {
"https://hello.com",
1,
TERM_SEARCH,
- null
+ null,
+ 60000
)
val inputErrorsCaptor = argumentCaptor()
@@ -246,7 +251,8 @@ class ViewSitePresenterTest {
"https://hello.com",
1,
JAVASCRIPT,
- null
+ null,
+ 60000
)
val inputErrorsCaptor = argumentCaptor()
@@ -258,6 +264,25 @@ class ViewSitePresenterTest {
assertThat(errors.javaScript).isEqualTo(R.string.please_enter_javaScript)
}
+ @Test fun commit_networkTimeout_error() {
+ presenter.commit(
+ "Testing",
+ "https://hello.com",
+ 1,
+ STATUS_CODE,
+ null,
+ 0
+ )
+
+ val inputErrorsCaptor = argumentCaptor()
+ verify(view).setInputErrors(inputErrorsCaptor.capture())
+ verify(checkStatusManager, never())
+ .scheduleCheck(any(), any(), any(), any())
+
+ val errors = inputErrorsCaptor.firstValue
+ assertThat(errors.networkTimeout).isEqualTo(R.string.please_enter_networkTimeout)
+ }
+
@Test fun commit_success() = runBlocking {
val name = "Testing"
val url = "https://hello.com"
@@ -274,7 +299,8 @@ class ViewSitePresenterTest {
url,
checkInterval,
validationMode,
- validationContent
+ validationContent,
+ 60000
)
val modelCaptor = argumentCaptor()
@@ -358,4 +384,4 @@ class ViewSitePresenterTest {
on { getAction() } doReturn action
}
}
-}
\ No newline at end of file
+}
diff --git a/data/src/main/java/com/afollestad/nocknock/data/ServerModel.kt b/data/src/main/java/com/afollestad/nocknock/data/ServerModel.kt
index ecba970..b98931f 100644
--- a/data/src/main/java/com/afollestad/nocknock/data/ServerModel.kt
+++ b/data/src/main/java/com/afollestad/nocknock/data/ServerModel.kt
@@ -27,7 +27,8 @@ data class ServerModel(
val reason: String? = null,
val validationMode: ValidationMode,
val validationContent: String? = null,
- val disabled: Boolean = false
+ val disabled: Boolean = false,
+ val networkTimeout: Int = 0
) : IdProvider {
companion object {
@@ -42,6 +43,7 @@ data class ServerModel(
const val COLUMN_VALIDATION_MODE = "validation_mode"
const val COLUMN_VALIDATION_CONTENT = "validation_content"
const val COLUMN_DISABLED = "disabled"
+ const val COLUMN_NETWORK_TIMEOUT = "network_timeout"
const val DEFAULT_SORT_ORDER = "$COLUMN_NAME ASC, $COLUMN_DISABLED DESC"
@@ -58,7 +60,8 @@ data class ServerModel(
cursor.getColumnIndex(COLUMN_VALIDATION_MODE)
).toValidationMode(),
validationContent = cursor.getString(cursor.getColumnIndex(COLUMN_VALIDATION_CONTENT)),
- disabled = cursor.getInt(cursor.getColumnIndex(COLUMN_DISABLED)) == 1
+ disabled = cursor.getInt(cursor.getColumnIndex(COLUMN_DISABLED)) == 1,
+ networkTimeout = cursor.getInt(cursor.getColumnIndex(COLUMN_NETWORK_TIMEOUT))
)
}
}
@@ -81,5 +84,6 @@ data class ServerModel(
put(COLUMN_VALIDATION_MODE, validationMode.value)
put(COLUMN_VALIDATION_CONTENT, validationContent)
put(COLUMN_DISABLED, disabled)
+ put(COLUMN_NETWORK_TIMEOUT, networkTimeout)
}
}
diff --git a/engine/src/main/java/com/afollestad/nocknock/engine/db/ServerModelDbHelper.kt b/engine/src/main/java/com/afollestad/nocknock/engine/db/ServerModelDbHelper.kt
index 4caaca1..d1bff17 100644
--- a/engine/src/main/java/com/afollestad/nocknock/engine/db/ServerModelDbHelper.kt
+++ b/engine/src/main/java/com/afollestad/nocknock/engine/db/ServerModelDbHelper.kt
@@ -21,7 +21,9 @@ private const val SQL_CREATE_ENTRIES =
"${ServerModel.COLUMN_REASON} TEXT," +
"${ServerModel.COLUMN_VALIDATION_MODE} INTEGER," +
"${ServerModel.COLUMN_VALIDATION_CONTENT} TEXT," +
- "${ServerModel.COLUMN_DISABLED} INTEGER)"
+ "${ServerModel.COLUMN_DISABLED} INTEGER," +
+ "${ServerModel.COLUMN_NETWORK_TIMEOUT} INTEGER" +
+ ")"
private const val SQL_DELETE_ENTRIES = "DROP TABLE IF EXISTS ${ServerModel.TABLE_NAME}"
@@ -30,7 +32,7 @@ class ServerModelDbHelper(context: Context) : SQLiteOpenHelper(
context, DATABASE_NAME, null, DATABASE_VERSION
) {
companion object {
- const val DATABASE_VERSION = 2
+ const val DATABASE_VERSION = 3
const val DATABASE_NAME = "ServerModels.db"
}
@@ -43,8 +45,12 @@ class ServerModelDbHelper(context: Context) : SQLiteOpenHelper(
oldVersion: Int,
newVersion: Int
) {
- db.execSQL(SQL_DELETE_ENTRIES)
- onCreate(db)
+ if (newVersion == 3 && oldVersion == 2) {
+ db.execSQL(
+ "ALTER TABLE ${ServerModel.TABLE_NAME} " +
+ "ADD COLUMN ${ServerModel.COLUMN_NETWORK_TIMEOUT} INTEGER DEFAULT 10000"
+ )
+ }
}
override fun onDowngrade(
diff --git a/engine/src/main/java/com/afollestad/nocknock/engine/statuscheck/CheckStatusManager.kt b/engine/src/main/java/com/afollestad/nocknock/engine/statuscheck/CheckStatusManager.kt
index 39e22fd..7b0c68e 100644
--- a/engine/src/main/java/com/afollestad/nocknock/engine/statuscheck/CheckStatusManager.kt
+++ b/engine/src/main/java/com/afollestad/nocknock/engine/statuscheck/CheckStatusManager.kt
@@ -19,7 +19,9 @@ import com.afollestad.nocknock.utilities.providers.StringProvider
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
+import org.jetbrains.annotations.TestOnly
import java.net.SocketTimeoutException
+import java.util.concurrent.TimeUnit.MILLISECONDS
import javax.inject.Inject
import timber.log.Timber.d as log
@@ -29,6 +31,8 @@ data class CheckResult(
val response: Response? = null
)
+typealias ClientTimeoutChanger = (client: OkHttpClient, timeout: Int) -> OkHttpClient
+
/** @author Aidan Follestad (@afollestad) */
interface CheckStatusManager {
@@ -55,6 +59,12 @@ class RealCheckStatusManager @Inject constructor(
private val siteStore: ServerModelStore
) : CheckStatusManager {
+ private var clientTimeoutChanger: ClientTimeoutChanger = { client, timeout ->
+ client.newBuilder()
+ .callTimeout(timeout.toLong(), MILLISECONDS)
+ .build()
+ }
+
override suspend fun ensureScheduledChecks() {
val sites = siteStore.get()
if (sites.isEmpty()) {
@@ -121,6 +131,7 @@ class RealCheckStatusManager @Inject constructor(
override suspend fun performCheck(site: ServerModel): CheckResult {
check(site.id != 0) { "Cannot schedule checks for jobs with no ID." }
+ check(site.networkTimeout > 0) { "Network timeout not set for site ${site.id}" }
log("performCheck(${site.id}) - GET ${site.url}")
val request = Request.Builder()
@@ -129,8 +140,10 @@ class RealCheckStatusManager @Inject constructor(
.build()
return try {
- val response = okHttpClient.newCall(request)
+ val client = clientTimeoutChanger(okHttpClient, site.networkTimeout)
+ val response = client.newCall(request)
.execute()
+
if (response.isSuccessful || response.code() == 401) {
log("performCheck(${site.id}) = Successful")
CheckResult(
@@ -164,4 +177,8 @@ class RealCheckStatusManager @Inject constructor(
private fun jobForSite(site: ServerModel) =
jobScheduler.allPendingJobs
.firstOrNull { job -> job.id == site.id }
+
+ @TestOnly fun setClientTimeoutChanger(changer: ClientTimeoutChanger) {
+ this.clientTimeoutChanger = changer
+ }
}
diff --git a/engine/src/test/java/com/afollestad/nocknock/engine/CheckStatusManagerTest.kt b/engine/src/test/java/com/afollestad/nocknock/engine/CheckStatusManagerTest.kt
index d931a50..71e45bb 100644
--- a/engine/src/test/java/com/afollestad/nocknock/engine/CheckStatusManagerTest.kt
+++ b/engine/src/test/java/com/afollestad/nocknock/engine/CheckStatusManagerTest.kt
@@ -55,7 +55,12 @@ class CheckStatusManagerTest {
bundleProvider,
jobInfoProvider,
store
- )
+ ).apply {
+ setClientTimeoutChanger { _, timeout ->
+ whenever(okHttpClient.callTimeoutMillis()).doReturn(timeout)
+ return@setClientTimeoutChanger okHttpClient
+ }
+ }
@Test fun ensureScheduledChecks_noEnabledSites() = runBlocking {
val model1 = fakeModel().copy(disabled = true)
@@ -234,6 +239,8 @@ class CheckStatusManagerTest {
reason = null
)
)
+ assertThat(okHttpClient.callTimeoutMillis())
+ .isEqualTo(model1.networkTimeout)
}
@Test fun performCheck_401_butStillSuccess() = runBlocking {
@@ -280,7 +287,8 @@ class CheckStatusManagerTest {
id = 1,
name = "Wakanda Forever",
url = "https://www.wakanda.gov",
- validationMode = STATUS_CODE
+ validationMode = STATUS_CODE,
+ networkTimeout = 60000
)
private fun fakeJob(id: Int): JobInfo {
diff --git a/utilities/src/main/java/com/afollestad/nocknock/utilities/ext/TimeExt.kt b/utilities/src/main/java/com/afollestad/nocknock/utilities/ext/TimeExt.kt
index b3fdc20..e659d16 100644
--- a/utilities/src/main/java/com/afollestad/nocknock/utilities/ext/TimeExt.kt
+++ b/utilities/src/main/java/com/afollestad/nocknock/utilities/ext/TimeExt.kt
@@ -24,7 +24,13 @@ fun Long.timeString() = when {
"${ceil((this.toFloat() / DAY.toFloat()).toDouble()).toInt()}d"
this >= HOUR ->
"${ceil((this.toFloat() / HOUR.toFloat()).toDouble()).toInt()}h"
- this >= MINUTE ->
- "${ceil((this.toFloat() / MINUTE.toFloat()).toDouble()).toInt()}m"
+ this >= MINUTE -> {
+ val result = "${ceil((this.toFloat() / MINUTE.toFloat()).toDouble()).toInt()}m"
+ if (result == "60m") {
+ "1h"
+ } else {
+ result
+ }
+ }
else -> "<1m"
}
diff --git a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/ext/TextViewExt.kt b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/ext/TextViewExt.kt
index fc34583..533a8f1 100644
--- a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/ext/TextViewExt.kt
+++ b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/ext/TextViewExt.kt
@@ -9,9 +9,14 @@ import android.widget.TextView
fun TextView.trimmedText() = text.toString().trim()
-fun TextView.textAsLong(): Long {
+fun TextView.textAsInt(defaultValue: Int = 0): Int {
val text = trimmedText()
- return if (text.isEmpty()) 0L else text.toLong()
+ return if (text.isEmpty()) defaultValue else text.toInt()
+}
+
+fun TextView.textAsLong(defaultValue: Long = 0L): Long {
+ val text = trimmedText()
+ return if (text.isEmpty()) defaultValue else text.toLong()
}
///** @author https://stackoverflow.com/a/53296137/309644 */