From 8f16ff2d331de8a6720308d68c7cac05e07665bb Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sun, 13 Jan 2019 15:16:33 -0800 Subject: [PATCH 01/42] AppDatabaseTest fix --- .idea/misc.xml | 2 +- .../java/com/afollestad/nocknock/data/AppDatabaseTest.kt | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 9d1e235..50f0406 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -40,7 +40,7 @@ - + diff --git a/data/src/androidTest/java/com/afollestad/nocknock/data/AppDatabaseTest.kt b/data/src/androidTest/java/com/afollestad/nocknock/data/AppDatabaseTest.kt index 463be68..db9edd7 100644 --- a/data/src/androidTest/java/com/afollestad/nocknock/data/AppDatabaseTest.kt +++ b/data/src/androidTest/java/com/afollestad/nocknock/data/AppDatabaseTest.kt @@ -181,7 +181,8 @@ class AppDatabaseTest() { validationMode = STATUS_CODE, validationArgs = null, disabled = false, - networkTimeout = 10000 + networkTimeout = 10000, + certificate = null ) val newId = settingsDao.insert(model) assertThat(newId).isEqualTo(1) @@ -199,7 +200,8 @@ class AppDatabaseTest() { validationMode = STATUS_CODE, validationArgs = null, disabled = false, - networkTimeout = 10000 + networkTimeout = 10000, + certificate = null ) ) @@ -227,7 +229,8 @@ class AppDatabaseTest() { validationMode = STATUS_CODE, validationArgs = null, disabled = false, - networkTimeout = 10000 + networkTimeout = 10000, + certificate = null ) ) From 77f939b095af7808f76aec86c8685d6b1e7d69bd Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 24 Jan 2019 14:32:38 -0800 Subject: [PATCH 02/42] Lots of dependency upgrades --- .idea/misc.xml | 2 +- dependencies.gradle | 12 ++++++------ gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 50f0406..9d1e235 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -40,7 +40,7 @@ - + diff --git a/dependencies.gradle b/dependencies.gradle index b6b8781..b9072c2 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -7,7 +7,7 @@ ext.versions = [ publishVersionCode : 39, // Plugins - gradlePlugin : '3.2.1', + gradlePlugin : '3.3.0', spotlessPlugin : '3.17.0', versionPlugin : '0.20.0', fabricPlugin : '1.+', @@ -17,8 +17,8 @@ ext.versions = [ rhino : '1.7.10', // Kotlin - kotlin : '1.3.11', - coroutines : '1.1.0', + kotlin : '1.3.20', + coroutines : '1.1.1', koin : '1.0.2', // Google/AndroidX @@ -34,8 +34,8 @@ ext.versions = [ rxBinding : '3.0.0-alpha1', // afollestad - materialDialogs : '2.0.0-rc7', - rxkPrefs : '1.2.1', + materialDialogs : '2.0.0-rc8', + rxkPrefs : '1.2.2', // Debugging timber : '4.7.1', @@ -44,7 +44,7 @@ ext.versions = [ // Unit testing junit : '4.12', mockito : '2.23.4', - mockitoKotlin : '2.0.0-RC1', + mockitoKotlin : '2.1.0', truth : '0.42', // UI testing diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1c0396b..8ab96fb 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-bin.zip From 571e7ebff3ffdc5e4b6c8780269e59237f34853d Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 24 Jan 2019 16:03:12 -0800 Subject: [PATCH 03/42] Pull Fabric props from environment variables, default to 0 which stops build failures --- .editorconfig | 3 --- .idea/misc.xml | 2 +- app/build.gradle | 13 +----------- app/src/release/AndroidManifest.xml | 14 ------------- fabric.gradle | 32 +++++++++++++++++++++++++++++ 5 files changed, 34 insertions(+), 30 deletions(-) delete mode 100644 .editorconfig delete mode 100644 app/src/release/AndroidManifest.xml create mode 100644 fabric.gradle diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 17bc1fa..0000000 --- a/.editorconfig +++ /dev/null @@ -1,3 +0,0 @@ -[*.kt] -indent_size = 2 -continuation_indent_size=4 \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 9d1e235..50f0406 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -40,7 +40,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 6b0bbbe..efff452 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,17 +4,7 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-android-extensions' -apply plugin: 'io.fabric' - -def getFabricApiKey() { - def propsFile = project.rootProject.file('local.properties') - if (!propsFile.exists()) { - return "" - } - Properties properties = new Properties() - properties.load(propsFile.newDataInputStream()) - return properties.getProperty("fabric.apikey") ?: "" -} +apply from: '../fabric.gradle' android { compileSdkVersion versions.compileSdk @@ -26,7 +16,6 @@ android { targetSdkVersion versions.compileSdk versionCode versions.publishVersionCode versionName versions.publishVersion - manifestPlaceholders = [fabricKey:getFabricApiKey()] } buildTypes { diff --git a/app/src/release/AndroidManifest.xml b/app/src/release/AndroidManifest.xml deleted file mode 100644 index f557bb7..0000000 --- a/app/src/release/AndroidManifest.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - diff --git a/fabric.gradle b/fabric.gradle new file mode 100644 index 0000000..8303700 --- /dev/null +++ b/fabric.gradle @@ -0,0 +1,32 @@ +apply plugin: 'io.fabric' + +ext.getFabricApiKey = { + return System.getenv('FABRIC_APIKEY') ?: "0" +} + +ext.getFabricApiSecret = { + return System.getenv('FABRIC_APISECRET') ?: "0" +} + +def buildFabricProperties() { + def propertiesFile = file("fabric.properties") + def apiSecret = getFabricApiSecret() + def apiKey = getFabricApiKey() + + if (apiSecret == "0" || apiKey == "0") { + logger.warn("API key and/or secret env variables not found, defaulting to 0.") + } + if (propertiesFile.exists()) { + propertiesFile.delete() + } + + def commentMessage = "suppress inspection \"UnusedProperty\" for whole file" + ant.propertyfile(file: "fabric.properties", comment: commentMessage) { + entry(key: "apiSecret", value: apiSecret) + entry(key: "apiKey", value: apiKey) + } +} + +afterEvaluate { + buildFabricProperties() +} \ No newline at end of file From f86ccbbe0c273e1422d4f5603db42349fdc83697 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Fri, 25 Jan 2019 11:08:18 -0800 Subject: [PATCH 04/42] Add default Fabric props that should fix CI --- fabric.gradle | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fabric.gradle b/fabric.gradle index 8303700..315dff2 100644 --- a/fabric.gradle +++ b/fabric.gradle @@ -1,11 +1,11 @@ apply plugin: 'io.fabric' ext.getFabricApiKey = { - return System.getenv('FABRIC_APIKEY') ?: "0" + return System.getenv('FABRIC_APIKEY') ?: "xxxe76c4xxxx97e8cxxxx0135e9d46f5a2xxx" } ext.getFabricApiSecret = { - return System.getenv('FABRIC_APISECRET') ?: "0" + return System.getenv('FABRIC_APISECRET') ?: "xx68f6074dxxxxxc11dxxx97c172e8ebf0" } def buildFabricProperties() { @@ -13,9 +13,6 @@ def buildFabricProperties() { def apiSecret = getFabricApiSecret() def apiKey = getFabricApiKey() - if (apiSecret == "0" || apiKey == "0") { - logger.warn("API key and/or secret env variables not found, defaulting to 0.") - } if (propertiesFile.exists()) { propertiesFile.delete() } From 859dcb53cabe0c091e1ada0169e335d1b0649171 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sat, 26 Jan 2019 12:36:20 -0800 Subject: [PATCH 05/42] MD rc9 --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index b9072c2..661f7d6 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -34,7 +34,7 @@ ext.versions = [ rxBinding : '3.0.0-alpha1', // afollestad - materialDialogs : '2.0.0-rc8', + materialDialogs : '2.0.0-rc9', rxkPrefs : '1.2.2', // Debugging From 7dc4ee7fb14d4423089aa45c756400f9b70fc0ab Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sat, 26 Jan 2019 12:39:46 -0800 Subject: [PATCH 06/42] Add vvalidator dep --- .idea/misc.xml | 2 +- app/build.gradle | 1 + dependencies.gradle | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 50f0406..9d1e235 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -40,7 +40,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index efff452..49546d3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,6 +55,7 @@ dependencies { // afollestad implementation 'com.afollestad.material-dialogs:core:' + versions.materialDialogs + implementation 'com.afollestad:vvalidator:' + versions.vvalidator // Debugging implementation 'com.jakewharton.timber:timber:' + versions.timber diff --git a/dependencies.gradle b/dependencies.gradle index 661f7d6..fd28b7d 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -36,6 +36,7 @@ ext.versions = [ // afollestad materialDialogs : '2.0.0-rc9', rxkPrefs : '1.2.2', + vvalidator : '0.2.2', // Debugging timber : '4.7.1', From b3f8a43f71c5c635a0ec6068a8f0aa252c9ad94d Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sat, 26 Jan 2019 13:55:34 -0800 Subject: [PATCH 07/42] Use vvalidator in the add site page --- app/build.gradle | 1 - .../nocknock/ui/addsite/AddSiteActivity.kt | 65 +++-- .../nocknock/ui/addsite/AddSiteViewModel.kt | 116 +-------- app/src/main/res/values/strings.xml | 2 - .../ui/addsite/AddSiteViewModelTest.kt | 244 ------------------ viewcomponents/build.gradle | 2 + .../nocknock/viewcomponents/ext/ViewExt.kt | 10 +- .../interval/ValidationIntervalLayout.kt | 16 +- .../js/JavaScriptInputLayout.kt | 19 +- .../src/main/res/values/strings.xml | 4 + 10 files changed, 79 insertions(+), 400 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 49546d3..efff452 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -55,7 +55,6 @@ dependencies { // afollestad implementation 'com.afollestad.material-dialogs:core:' + versions.materialDialogs - implementation 'com.afollestad:vvalidator:' + versions.vvalidator // Debugging implementation 'com.jakewharton.timber:timber:' + versions.timber 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 26a21f9..1c38e97 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 @@ -31,11 +31,13 @@ import com.afollestad.nocknock.utilities.ext.onTextChanged import com.afollestad.nocknock.utilities.ext.setTextAndMaintainSelection import com.afollestad.nocknock.utilities.livedata.distinct import com.afollestad.nocknock.viewcomponents.ext.dimenFloat +import com.afollestad.nocknock.viewcomponents.ext.isVisibleCondition import com.afollestad.nocknock.viewcomponents.ext.onScroll import com.afollestad.nocknock.viewcomponents.livedata.attachLiveData -import com.afollestad.nocknock.viewcomponents.livedata.toViewError import com.afollestad.nocknock.viewcomponents.livedata.toViewText import com.afollestad.nocknock.viewcomponents.livedata.toViewVisibility +import com.afollestad.vvalidator.form +import com.afollestad.vvalidator.form.Form import kotlinx.android.synthetic.main.activity_addsite.checkIntervalLayout import kotlinx.android.synthetic.main.activity_addsite.headersLayout import kotlinx.android.synthetic.main.activity_addsite.inputName @@ -64,13 +66,15 @@ class AddSiteActivity : DarkModeSwitchActivity() { } private val viewModel by viewModel() + private lateinit var validationForm: Form @SuppressLint("SetTextI18n") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_addsite) - setupUi() + setupUi() + setupValidation() lifecycle.addObserver(viewModel) // Populate view model with initial data @@ -82,23 +86,17 @@ class AddSiteActivity : DarkModeSwitchActivity() { // Name inputName.attachLiveData(this, viewModel.name) - viewModel.onNameError() - .toViewError(this, inputName) // Tags inputTags.attachLiveData(this, viewModel.tags) // Url inputUrl.attachLiveData(this, viewModel.url) - viewModel.onUrlError() - .toViewError(this, inputUrl) viewModel.onUrlWarningVisibility() .toViewVisibility(this, textUrlWarning) // Timeout responseTimeoutInput.attachLiveData(this, viewModel.timeout) - viewModel.onTimeoutError() - .toViewError(this, responseTimeoutInput) // Validation mode responseValidationMode.attachLiveData( @@ -107,8 +105,6 @@ class AddSiteActivity : DarkModeSwitchActivity() { outTransformer = { ValidationMode.fromIndex(it) }, inTransformer = { it.toIndex() } ) - viewModel.onValidationSearchTermError() - .toViewError(this, responseValidationSearchTerm) viewModel.onValidationModeDescription() .toViewText(this, validationModeDescription) @@ -124,15 +120,15 @@ class AddSiteActivity : DarkModeSwitchActivity() { // Validation script scriptInputLayout.attach( codeData = viewModel.validationScript, - errorData = viewModel.onValidationScriptError(), - visibility = viewModel.onValidationScriptVisibility() + visibility = viewModel.onValidationScriptVisibility(), + form = validationForm ) // Check interval checkIntervalLayout.attach( valueData = viewModel.checkIntervalValue, multiplierData = viewModel.checkIntervalUnit, - errorData = viewModel.onCheckIntervalError() + form = validationForm ) // Retry Policy @@ -145,8 +141,6 @@ class AddSiteActivity : DarkModeSwitchActivity() { sslCertificateInput.onTextChanged { viewModel.certificateUri.value = it } viewModel.certificateUri.distinct() .observe(this, Observer { sslCertificateInput.setTextAndMaintainSelection(it) }) - viewModel.onCertificateError() - .toViewError(this, sslCertificateInput) // Headers headersLayout.attach(viewModel.headers) @@ -156,15 +150,6 @@ class AddSiteActivity : DarkModeSwitchActivity() { toolbarTitle.setText(R.string.add_site) toolbar.run { inflateMenu(R.menu.menu_addsite) - setOnMenuItemClickListener { - if (it.itemId == R.id.commit) { - viewModel.commit { - setResult(RESULT_OK) - finish() - } - } - true - } setNavigationIcon(R.drawable.ic_action_close) setNavigationOnClickListener { finish() } } @@ -195,6 +180,38 @@ class AddSiteActivity : DarkModeSwitchActivity() { } } + private fun setupValidation() { + validationForm = form { + input(inputName, name = "Name") { + isNotEmpty().description(R.string.please_enter_name) + } + input(inputUrl, name = "URL") { + isNotEmpty().description(R.string.please_enter_url) + isUrl().description(R.string.please_enter_valid_url) + } + input(responseTimeoutInput, name = "Timeout", optional = true) { + isNumber().greaterThan(0) + .description(R.string.please_enter_networkTimeout) + } + input(responseValidationSearchTerm, name = "Search term") { + conditional(responseValidationSearchTerm.isVisibleCondition()) { + isNotEmpty().description(R.string.please_enter_search_term) + } + } + input(sslCertificateInput, name = "Certificate Path") { + isUri().hasScheme("file", "content") + .that { it.host != null } + .description(R.string.please_enter_validCertUri) + } + submitWith(toolbar.menu, R.id.commit) { + viewModel.commit { + setResult(RESULT_OK) + finish() + } + } + } + } + override fun onResume() { super.onResume() appToolbar.elevation = if (scrollView.scrollY > appToolbar.measuredHeight / 2) { diff --git a/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModel.kt b/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModel.kt index 87da65c..106f232 100644 --- a/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModel.kt +++ b/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModel.kt @@ -39,9 +39,7 @@ import com.afollestad.nocknock.data.putSite import com.afollestad.nocknock.engine.validation.ValidationExecutor import com.afollestad.nocknock.ui.ScopedViewModel import com.afollestad.nocknock.utilities.ext.MINUTE -import com.afollestad.nocknock.utilities.ext.toUri import com.afollestad.nocknock.utilities.livedata.map -import com.afollestad.nocknock.viewcomponents.ext.isNullOrLessThan import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -83,23 +81,10 @@ class AddSiteViewModel( headers.value = emptyList() } - // Private properties private val isLoading = MutableLiveData() - private val nameError = MutableLiveData() - private val urlError = MutableLiveData() - private val timeoutError = MutableLiveData() - private val validationSearchTermError = MutableLiveData() - private val validationScriptError = MutableLiveData() - private val checkIntervalValueError = MutableLiveData() - private val certificateError = MutableLiveData() - // Expose private properties or calculated properties @CheckResult fun onIsLoading(): LiveData = isLoading - @CheckResult fun onNameError(): LiveData = nameError - - @CheckResult fun onUrlError(): LiveData = urlError - @CheckResult fun onUrlWarningVisibility(): LiveData { return url.map { val parsed = HttpUrl.parse(it) @@ -107,8 +92,6 @@ class AddSiteViewModel( } } - @CheckResult fun onTimeoutError(): LiveData = timeoutError - @CheckResult fun onValidationModeDescription(): LiveData { return validationMode.map { when (it!!) { @@ -119,19 +102,9 @@ class AddSiteViewModel( } } - @CheckResult fun onValidationSearchTermError(): LiveData = validationSearchTermError + @CheckResult fun onValidationSearchTermVisibility() = validationMode.map { it == TERM_SEARCH } - @CheckResult fun onValidationSearchTermVisibility() = - validationMode.map { it == TERM_SEARCH } - - @CheckResult fun onValidationScriptError(): LiveData = validationScriptError - - @CheckResult fun onValidationScriptVisibility() = - validationMode.map { it == JAVASCRIPT } - - @CheckResult fun onCheckIntervalError(): LiveData = checkIntervalValueError - - @CheckResult fun onCertificateError(): LiveData = certificateError + @CheckResult fun onValidationScriptVisibility() = validationMode.map { it == JAVASCRIPT } // Actions fun commit(done: () -> Unit) { @@ -171,89 +144,7 @@ class AddSiteViewModel( } private fun generateDbModel(): Site? { - var errorCount = 0 - - // Validation name - if (name.value.isNullOrEmpty()) { - nameError.value = R.string.please_enter_name - errorCount++ - } else { - nameError.value = null - } - - // Validate URL - when { - url.value.isNullOrEmpty() -> { - urlError.value = R.string.please_enter_url - errorCount++ - } - HttpUrl.parse(url.value!!) == null -> { - urlError.value = R.string.please_enter_valid_url - errorCount++ - } - else -> { - urlError.value = null - } - } - - // Validate timeout val timeout = timeout.value ?: 10_000 - if (timeout < 0) { - timeoutError.value = R.string.please_enter_networkTimeout - errorCount++ - } else { - timeoutError.value = null - } - - // Validate check interval - if (checkIntervalValue.value.isNullOrLessThan(1)) { - checkIntervalValueError.value = R.string.please_enter_check_interval - errorCount++ - } else { - checkIntervalValueError.value = null - } - - // Validate arguments - if (validationMode.value == TERM_SEARCH && - validationSearchTerm.value.isNullOrEmpty() - ) { - errorCount++ - validationSearchTermError.value = R.string.please_enter_search_term - validationScriptError.value = null - } else if (validationMode.value == JAVASCRIPT && - validationScript.value.isNullOrEmpty() - ) { - errorCount++ - validationSearchTermError.value = null - validationScriptError.value = R.string.please_enter_javaScript - } else { - validationSearchTermError.value = null - validationScriptError.value = null - } - - // Validate SSL certificate - val certString = certificateUri.value - if (certString != null) { - val rawCertUri = certString.toUri() - val certUri = if (rawCertUri.scheme == null) { - rawCertUri.buildUpon() - .scheme("file") - .build() - } else { - rawCertUri - } - if (certUri.scheme != "content" && certUri.scheme != "file") { - errorCount++ - certificateError.value = R.string.please_enter_validCertUri - } else { - certificateError.value = null - } - } - - if (errorCount > 0) { - return null - } - val cleanedTags = tags.value?.split(',')?.joinToString { it.trim() } ?: "" val newSettings = SiteSettings( @@ -275,7 +166,8 @@ class AddSiteViewModel( val retryPolicyMinutes = retryPolicyMinutes.value ?: 0 val newRetryPolicy: RetryPolicy? = if (retryPolicyTimes > 0 && retryPolicyMinutes > 0) { RetryPolicy( - count = retryPolicyTimes, minutes = retryPolicyMinutes + count = retryPolicyTimes, + minutes = retryPolicyMinutes ) } else { null diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2b09271..2267417 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -29,9 +29,7 @@ Please enter a name! Please enter a URL. Please enter a valid URL. - Please input a validation interval. Please input a search term. - Please input a validation script. Please enter a network timeout greater than 0. Certificate should be a valid file or content URI. diff --git a/app/src/test/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModelTest.kt b/app/src/test/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModelTest.kt index eb86c29..b62f9a6 100644 --- a/app/src/test/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModelTest.kt +++ b/app/src/test/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModelTest.kt @@ -149,247 +149,9 @@ class AddSiteViewModelTest { assertThat(viewModel.getValidationArgs()).isEqualTo("Two") } - @Test fun commit_nameError() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - name.value = "" - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertValues(R.string.please_enter_name) - onUrlError.assertNoValues() - onTimeoutError.assertNoValues() - onCheckIntervalError.assertNoValues() - onSearchTermError.assertNoValues() - onScriptError.assertNoValues() - - verify(onDone, never()).invoke() - } - - @Test fun commit_urlEmptyError() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - url.value = "" - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertNoValues() - onUrlError.assertValues(R.string.please_enter_url) - onTimeoutError.assertNoValues() - onCheckIntervalError.assertNoValues() - onSearchTermError.assertNoValues() - onScriptError.assertNoValues() - - verify(onDone, never()).invoke() - } - - @Test fun commit_urlFormatError() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - url.value = "ftp://www.idk.com" - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertNoValues() - onUrlError.assertValues(R.string.please_enter_valid_url) - onTimeoutError.assertNoValues() - onCheckIntervalError.assertNoValues() - onSearchTermError.assertNoValues() - onScriptError.assertNoValues() - - verify(onDone, never()).invoke() - } - - @Test fun commit_networkTimeout_error() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - timeout.value = 0 - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertNoValues() - onUrlError.assertNoValues() - onTimeoutError.assertValues(R.string.please_enter_networkTimeout) - onCheckIntervalError.assertNoValues() - onSearchTermError.assertNoValues() - onScriptError.assertNoValues() - - verify(onDone, never()).invoke() - } - - @Test fun commit_checkIntervalError() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - checkIntervalValue.value = 0 - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertNoValues() - onUrlError.assertNoValues() - onTimeoutError.assertNoValues() - onCheckIntervalError.assertValues(R.string.please_enter_check_interval) - onSearchTermError.assertNoValues() - onScriptError.assertNoValues() - - verify(onDone, never()).invoke() - } - - @Test fun commit_termSearchError() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - validationMode.value = TERM_SEARCH - validationSearchTerm.value = "" - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertNoValues() - onUrlError.assertNoValues() - onTimeoutError.assertNoValues() - onCheckIntervalError.assertNoValues() - onSearchTermError.assertValues(R.string.please_enter_search_term) - onScriptError.assertNoValues() - - verify(onDone, never()).invoke() - } - - @Test fun commit_javaScript_error() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - validationMode.value = JAVASCRIPT - validationScript.value = "" - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertNoValues() - onUrlError.assertNoValues() - onTimeoutError.assertNoValues() - onCheckIntervalError.assertNoValues() - onSearchTermError.assertNoValues() - onScriptError.assertValues(R.string.please_enter_javaScript) - - verify(onDone, never()).invoke() - } - @Test fun commit_success() = runBlocking { val isLoading = viewModel.onIsLoading() .test() - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() fillInModel() val onDone = mock<() -> Unit>() @@ -416,12 +178,6 @@ class AddSiteViewModelTest { cancelPrevious = true, fromFinishingJob = false ) - onNameError.assertNoValues() - onUrlError.assertNoValues() - onTimeoutError.assertNoValues() - onCheckIntervalError.assertNoValues() - onSearchTermError.assertNoValues() - onScriptError.assertNoValues() verify(onDone).invoke() } diff --git a/viewcomponents/build.gradle b/viewcomponents/build.gradle index 8b7cc90..a3ae3dc 100644 --- a/viewcomponents/build.gradle +++ b/viewcomponents/build.gradle @@ -18,6 +18,8 @@ dependencies { implementation project(':common') implementation project(':data') + api 'com.afollestad:vvalidator:' + versions.vvalidator + implementation 'androidx.appcompat:appcompat:' + versions.androidxCore implementation 'com.google.android.material:material:' + versions.googleMaterial api 'androidx.lifecycle:lifecycle-extensions:' + versions.lifecycle diff --git a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/ext/ViewExt.kt b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/ext/ViewExt.kt index feeef85..445c931 100644 --- a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/ext/ViewExt.kt +++ b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/ext/ViewExt.kt @@ -17,19 +17,15 @@ package com.afollestad.nocknock.viewcomponents.ext import android.view.View import android.view.View.GONE -import android.view.View.INVISIBLE import android.view.View.VISIBLE import android.view.ViewTreeObserver import androidx.annotation.DimenRes +import com.afollestad.vvalidator.form.Condition fun View.show() { visibility = VISIBLE } -fun View.conceal() { - visibility = INVISIBLE -} - fun View.hide() { visibility = GONE } @@ -51,3 +47,7 @@ fun View.onLayout(cb: () -> Unit) { fun View.dimenFloat(@DimenRes res: Int) = resources.getDimension(res) fun View.dimenInt(@DimenRes res: Int) = resources.getDimensionPixelSize(res) + +fun View.isVisibleCondition(): Condition = { + visibility == VISIBLE +} diff --git a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/interval/ValidationIntervalLayout.kt b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/interval/ValidationIntervalLayout.kt index 3436dd5..2db60fe 100644 --- a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/interval/ValidationIntervalLayout.kt +++ b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/interval/ValidationIntervalLayout.kt @@ -19,7 +19,6 @@ import android.content.Context import android.util.AttributeSet import android.widget.ArrayAdapter import android.widget.LinearLayout -import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.afollestad.nocknock.utilities.ext.DAY import com.afollestad.nocknock.utilities.ext.HOUR @@ -28,7 +27,7 @@ import com.afollestad.nocknock.utilities.ext.WEEK import com.afollestad.nocknock.viewcomponents.R import com.afollestad.nocknock.viewcomponents.livedata.attachLiveData import com.afollestad.nocknock.viewcomponents.livedata.lifecycleOwner -import com.afollestad.nocknock.viewcomponents.livedata.toViewError +import com.afollestad.vvalidator.form.Form import kotlinx.android.synthetic.main.validation_interval_layout.view.input import kotlinx.android.synthetic.main.validation_interval_layout.view.spinner @@ -66,8 +65,14 @@ class ValidationIntervalLayout( fun attach( valueData: MutableLiveData, multiplierData: MutableLiveData, - errorData: LiveData + form: Form ) { + form.input(input, name = "Interval") { + isNotEmpty().description(R.string.please_enter_check_interval) + length().greaterThan(0) + .description(R.string.check_interval_must_be_greater_zero) + } + input.attachLiveData(lifecycleOwner(), valueData) spinner.attachLiveData( lifecycleOwner = lifecycleOwner(), @@ -91,10 +96,5 @@ class ValidationIntervalLayout( } } ) - errorData.toViewError(lifecycleOwner(), this, ::setError) - } - - private fun setError(error: String?) { - input.error = error } } diff --git a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/js/JavaScriptInputLayout.kt b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/js/JavaScriptInputLayout.kt index 5d32e69..176f32d 100644 --- a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/js/JavaScriptInputLayout.kt +++ b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/js/JavaScriptInputLayout.kt @@ -20,15 +20,17 @@ import android.util.AttributeSet import android.widget.HorizontalScrollView import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData +import com.afollestad.nocknock.viewcomponents.R import com.afollestad.nocknock.viewcomponents.R.dimen import com.afollestad.nocknock.viewcomponents.R.layout import com.afollestad.nocknock.viewcomponents.ext.dimenFloat import com.afollestad.nocknock.viewcomponents.ext.dimenInt +import com.afollestad.nocknock.viewcomponents.ext.isVisibleCondition import com.afollestad.nocknock.viewcomponents.ext.showOrHide import com.afollestad.nocknock.viewcomponents.livedata.attachLiveData import com.afollestad.nocknock.viewcomponents.livedata.lifecycleOwner -import com.afollestad.nocknock.viewcomponents.livedata.toViewError import com.afollestad.nocknock.viewcomponents.livedata.toViewVisibility +import com.afollestad.vvalidator.form.Form import kotlinx.android.synthetic.main.javascript_input_layout.view.error_text import kotlinx.android.synthetic.main.javascript_input_layout.view.userInput @@ -55,11 +57,20 @@ class JavaScriptInputLayout( fun attach( codeData: MutableLiveData, - errorData: LiveData, - visibility: LiveData + visibility: LiveData, + form: Form ) { + form.input(userInput, name = "Script") { + conditional(isVisibleCondition()) { + isNotEmpty().description(R.string.please_enter_javaScript) + } + onErrors { _, errors -> + val error = errors.firstOrNull() + setError(error.toString()) + } + } + userInput.attachLiveData(lifecycleOwner(), codeData) - errorData.toViewError(lifecycleOwner(), this, ::setError) visibility.toViewVisibility(lifecycleOwner(), this) } diff --git a/viewcomponents/src/main/res/values/strings.xml b/viewcomponents/src/main/res/values/strings.xml index b2462ec..a8f5d3f 100644 --- a/viewcomponents/src/main/res/values/strings.xml +++ b/viewcomponents/src/main/res/values/strings.xml @@ -23,4 +23,8 @@ Header Name Header Value + Please input a validation interval. + The validation interval must be greater than 0. + Please input a validation script. + From c6fca52fe4e1e395f1653c4f0bd31d014e0f226b Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sat, 26 Jan 2019 14:10:58 -0800 Subject: [PATCH 08/42] Use vvalidator in the view site page --- .../nocknock/ui/addsite/AddSiteActivity.kt | 2 +- .../nocknock/ui/viewsite/ViewSiteActivity.kt | 52 ++-- .../nocknock/ui/viewsite/ViewSiteViewModel.kt | 124 +-------- .../ui/viewsite/ViewSiteViewModelTest.kt | 246 ------------------ 4 files changed, 47 insertions(+), 377 deletions(-) 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 1c38e97..9713b99 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 @@ -72,9 +72,9 @@ class AddSiteActivity : DarkModeSwitchActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_addsite) - setupUi() setupValidation() + lifecycle.addObserver(viewModel) // Populate view model with initial data 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 358dfd1..f5f4dcc 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 @@ -32,11 +32,13 @@ import com.afollestad.nocknock.utilities.ext.setTextAndMaintainSelection import com.afollestad.nocknock.utilities.livedata.distinct import com.afollestad.nocknock.utilities.providers.IntentProvider import com.afollestad.nocknock.viewcomponents.ext.dimenFloat +import com.afollestad.nocknock.viewcomponents.ext.isVisibleCondition import com.afollestad.nocknock.viewcomponents.ext.onScroll import com.afollestad.nocknock.viewcomponents.livedata.attachLiveData -import com.afollestad.nocknock.viewcomponents.livedata.toViewError import com.afollestad.nocknock.viewcomponents.livedata.toViewText import com.afollestad.nocknock.viewcomponents.livedata.toViewVisibility +import com.afollestad.vvalidator.form +import com.afollestad.vvalidator.form.Form import kotlinx.android.synthetic.main.activity_viewsite.checkIntervalLayout import kotlinx.android.synthetic.main.activity_viewsite.headersLayout import kotlinx.android.synthetic.main.activity_viewsite.iconStatus @@ -69,6 +71,7 @@ class ViewSiteActivity : DarkModeSwitchActivity() { } internal val viewModel by viewModel() + private lateinit var validationForm: Form private val intentProvider by inject() private val statusUpdateReceiver by lazy { @@ -82,6 +85,7 @@ class ViewSiteActivity : DarkModeSwitchActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_viewsite) setupUi() + setupValidation() lifecycle.run { addObserver(viewModel) @@ -103,23 +107,17 @@ class ViewSiteActivity : DarkModeSwitchActivity() { // Name inputName.attachLiveData(this, viewModel.name) - viewModel.onNameError() - .toViewError(this, inputName) // Tags inputTags.attachLiveData(this, viewModel.tags) // Url inputUrl.attachLiveData(this, viewModel.url) - viewModel.onUrlError() - .toViewError(this, inputUrl) viewModel.onUrlWarningVisibility() .toViewVisibility(this, textUrlWarning) // Timeout responseTimeoutInput.attachLiveData(this, viewModel.timeout) - viewModel.onTimeoutError() - .toViewError(this, responseTimeoutInput) // Validation mode responseValidationMode.attachLiveData( @@ -128,8 +126,6 @@ class ViewSiteActivity : DarkModeSwitchActivity() { outTransformer = { ValidationMode.fromIndex(it) }, inTransformer = { it.toIndex() } ) - viewModel.onValidationSearchTermError() - .toViewError(this, responseValidationSearchTerm) viewModel.onValidationModeDescription() .toViewText(this, validationModeDescription) @@ -141,15 +137,15 @@ class ViewSiteActivity : DarkModeSwitchActivity() { // Validation script scriptInputLayout.attach( codeData = viewModel.validationScript, - errorData = viewModel.onValidationScriptError(), - visibility = viewModel.onValidationScriptVisibility() + visibility = viewModel.onValidationScriptVisibility(), + form = validationForm ) // Check interval checkIntervalLayout.attach( valueData = viewModel.checkIntervalValue, multiplierData = viewModel.checkIntervalUnit, - errorData = viewModel.onCheckIntervalError() + form = validationForm ) // Retry Policy @@ -162,8 +158,6 @@ class ViewSiteActivity : DarkModeSwitchActivity() { sslCertificateInput.onTextChanged { viewModel.certificateUri.value = it } viewModel.certificateUri.distinct() .observe(this, Observer { sslCertificateInput.setTextAndMaintainSelection(it) }) - viewModel.onCertificateError() - .toViewError(this, sslCertificateInput) // Headers headersLayout.attach(viewModel.headers) @@ -190,7 +184,6 @@ class ViewSiteActivity : DarkModeSwitchActivity() { setOnMenuItemClickListener { when (it.itemId) { - R.id.commit -> viewModel.commit { finish() } R.id.remove -> maybeRemoveSite() R.id.disableChecks -> maybeDisableChecks() } @@ -238,6 +231,35 @@ class ViewSiteActivity : DarkModeSwitchActivity() { } } + private fun setupValidation() { + validationForm = form { + input(inputName, name = "Name") { + isNotEmpty().description(R.string.please_enter_name) + } + input(inputUrl, name = "URL") { + isNotEmpty().description(R.string.please_enter_url) + isUrl().description(R.string.please_enter_valid_url) + } + input(responseTimeoutInput, name = "Timeout", optional = true) { + isNumber().greaterThan(0) + .description(R.string.please_enter_networkTimeout) + } + input(responseValidationSearchTerm, name = "Search term") { + conditional(responseValidationSearchTerm.isVisibleCondition()) { + isNotEmpty().description(R.string.please_enter_search_term) + } + } + input(sslCertificateInput, name = "Certificate Path") { + isUri().hasScheme("file", "content") + .that { it.host != null } + .description(R.string.please_enter_validCertUri) + } + submitWith(toolbar.menu, R.id.commit) { + viewModel.commit { finish() } + } + } + } + override fun onResume() { super.onResume() appToolbar.elevation = if (scrollView.scrollY > appToolbar.measuredHeight / 2) { diff --git a/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModel.kt b/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModel.kt index 91c3125..bc910b9 100644 --- a/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModel.kt +++ b/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModel.kt @@ -40,11 +40,9 @@ import com.afollestad.nocknock.engine.validation.ValidationExecutor import com.afollestad.nocknock.notifications.NockNotificationManager import com.afollestad.nocknock.ui.ScopedViewModel import com.afollestad.nocknock.utilities.ext.formatDate -import com.afollestad.nocknock.utilities.ext.toUri import com.afollestad.nocknock.utilities.livedata.map import com.afollestad.nocknock.utilities.livedata.zip import com.afollestad.nocknock.utilities.providers.StringProvider -import com.afollestad.nocknock.viewcomponents.ext.isNullOrLessThan import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -81,23 +79,10 @@ class ViewSiteViewModel( internal val disabled = MutableLiveData() internal val lastResult = MutableLiveData() - // Private properties private val isLoading = MutableLiveData() - private val nameError = MutableLiveData() - private val urlError = MutableLiveData() - private val timeoutError = MutableLiveData() - private val validationSearchTermError = MutableLiveData() - private val validationScriptError = MutableLiveData() - private val checkIntervalValueError = MutableLiveData() - private val certificateError = MutableLiveData() - // Expose private properties or calculated properties @CheckResult fun onIsLoading(): LiveData = isLoading - @CheckResult fun onNameError(): LiveData = nameError - - @CheckResult fun onUrlError(): LiveData = urlError - @CheckResult fun onUrlWarningVisibility(): LiveData { return url.map { val parsed = HttpUrl.parse(it) @@ -105,8 +90,6 @@ class ViewSiteViewModel( } } - @CheckResult fun onTimeoutError(): LiveData = timeoutError - @CheckResult fun onValidationModeDescription(): LiveData { return validationMode.map { when (it!!) { @@ -117,22 +100,11 @@ class ViewSiteViewModel( } } - @CheckResult fun onValidationSearchTermError(): LiveData = validationSearchTermError + @CheckResult fun onValidationSearchTermVisibility() = validationMode.map { it == TERM_SEARCH } - @CheckResult fun onValidationSearchTermVisibility() = - validationMode.map { it == TERM_SEARCH } + @CheckResult fun onValidationScriptVisibility() = validationMode.map { it == JAVASCRIPT } - @CheckResult fun onValidationScriptError(): LiveData = validationScriptError - - @CheckResult fun onValidationScriptVisibility() = - validationMode.map { it == JAVASCRIPT } - - @CheckResult fun onCheckIntervalError(): LiveData = checkIntervalValueError - - @CheckResult fun onDisableChecksVisibility(): LiveData = - disabled.map { !it } - - @CheckResult fun onCertificateError(): LiveData = certificateError + @CheckResult fun onDisableChecksVisibility(): LiveData = disabled.map { !it } @CheckResult fun onDoneButtonText(): LiveData = disabled.map { @@ -250,89 +222,7 @@ class ViewSiteViewModel( } private fun getUpdatedDbModel(): Site? { - var errorCount = 0 - - // Validation name - if (name.value.isNullOrEmpty()) { - nameError.value = R.string.please_enter_name - errorCount++ - } else { - nameError.value = null - } - - // Validate URL - when { - url.value.isNullOrEmpty() -> { - urlError.value = R.string.please_enter_url - errorCount++ - } - HttpUrl.parse(url.value!!) == null -> { - urlError.value = R.string.please_enter_valid_url - errorCount++ - } - else -> { - urlError.value = null - } - } - - // Validate timeout val timeout = timeout.value ?: 10_000 - if (timeout < 0) { - timeoutError.value = R.string.please_enter_networkTimeout - errorCount++ - } else { - timeoutError.value = null - } - - // Validate check interval - if (checkIntervalValue.value.isNullOrLessThan(1)) { - checkIntervalValueError.value = R.string.please_enter_check_interval - errorCount++ - } else { - checkIntervalValueError.value = null - } - - // Validate arguments - if (validationMode.value == TERM_SEARCH && - validationSearchTerm.value.isNullOrEmpty() - ) { - errorCount++ - validationSearchTermError.value = R.string.please_enter_search_term - validationScriptError.value = null - } else if (validationMode.value == JAVASCRIPT && - validationScript.value.isNullOrEmpty() - ) { - errorCount++ - validationSearchTermError.value = null - validationScriptError.value = R.string.please_enter_javaScript - } else { - validationSearchTermError.value = null - validationScriptError.value = null - } - - // Validate SSL certificate - val certString = certificateUri.value - if (certString != null) { - val rawCertUri = certString.toUri() - val certUri = if (rawCertUri.scheme == null) { - rawCertUri.buildUpon() - .scheme("file") - .build() - } else { - rawCertUri - } - if (certUri.scheme != "content" && certUri.scheme != "file") { - errorCount++ - certificateError.value = R.string.please_enter_validCertUri - } else { - certificateError.value = null - } - } - - if (errorCount > 0) { - return null - } - val cleanedTags = tags.value?.split(',')?.joinToString { it.trim() } ?: "" val newSettings = site.settings!!.copy( @@ -349,11 +239,15 @@ class ViewSiteViewModel( val retryPolicy: RetryPolicy? = if (retryPolicyTimes > 0 && retryPolicyMinutes > 0) { if (site.retryPolicy != null) { // Have existing policy, update it - site.retryPolicy!!.copy(count = retryPolicyTimes, minutes = retryPolicyMinutes) + site.retryPolicy!!.copy( + count = retryPolicyTimes, + minutes = retryPolicyMinutes + ) } else { // Create new policy RetryPolicy( - count = retryPolicyTimes, minutes = retryPolicyMinutes + count = retryPolicyTimes, + minutes = retryPolicyMinutes ) } } else { diff --git a/app/src/test/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModelTest.kt b/app/src/test/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModelTest.kt index 39e017b..d7bc8a8 100644 --- a/app/src/test/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModelTest.kt +++ b/app/src/test/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModelTest.kt @@ -39,7 +39,6 @@ import com.nhaarman.mockitokotlin2.any import com.nhaarman.mockitokotlin2.argumentCaptor import com.nhaarman.mockitokotlin2.doAnswer import com.nhaarman.mockitokotlin2.mock -import com.nhaarman.mockitokotlin2.never import com.nhaarman.mockitokotlin2.verify import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -255,247 +254,9 @@ class ViewSiteViewModelTest { .isEqualTo("Two") } - @Test fun commit_nameError() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - name.value = "" - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertValues(R.string.please_enter_name) - onUrlError.assertNoValues() - onTimeoutError.assertNoValues() - onCheckIntervalError.assertNoValues() - onSearchTermError.assertNoValues() - onScriptError.assertNoValues() - - verify(onDone, never()).invoke() - } - - @Test fun commit_urlEmptyError() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - url.value = "" - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertNoValues() - onUrlError.assertValues(R.string.please_enter_url) - onTimeoutError.assertNoValues() - onCheckIntervalError.assertNoValues() - onSearchTermError.assertNoValues() - onScriptError.assertNoValues() - - verify(onDone, never()).invoke() - } - - @Test fun commit_urlFormatError() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - url.value = "ftp://www.idk.com" - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertNoValues() - onUrlError.assertValues(R.string.please_enter_valid_url) - onTimeoutError.assertNoValues() - onCheckIntervalError.assertNoValues() - onSearchTermError.assertNoValues() - onScriptError.assertNoValues() - - verify(onDone, never()).invoke() - } - - @Test fun commit_networkTimeout_error() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - timeout.value = 0 - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertNoValues() - onUrlError.assertNoValues() - onTimeoutError.assertValues(R.string.please_enter_networkTimeout) - onCheckIntervalError.assertNoValues() - onSearchTermError.assertNoValues() - onScriptError.assertNoValues() - - verify(onDone, never()).invoke() - } - - @Test fun commit_checkIntervalError() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - checkIntervalValue.value = 0 - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertNoValues() - onUrlError.assertNoValues() - onTimeoutError.assertNoValues() - onCheckIntervalError.assertValues(R.string.please_enter_check_interval) - onSearchTermError.assertNoValues() - onScriptError.assertNoValues() - - verify(onDone, never()).invoke() - } - - @Test fun commit_termSearchError() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - validationMode.value = TERM_SEARCH - validationSearchTerm.value = "" - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertNoValues() - onUrlError.assertNoValues() - onTimeoutError.assertNoValues() - onCheckIntervalError.assertNoValues() - onSearchTermError.assertValues(R.string.please_enter_search_term) - onScriptError.assertNoValues() - - verify(onDone, never()).invoke() - } - - @Test fun commit_javaScript_error() { - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - - fillInModel().apply { - validationMode.value = JAVASCRIPT - validationScript.value = "" - } - val onDone = mock<() -> Unit>() - viewModel.commit(onDone) - - verify(validationManager, never()) - .scheduleValidation(any(), any(), any(), any()) - onNameError.assertNoValues() - onUrlError.assertNoValues() - onTimeoutError.assertNoValues() - onCheckIntervalError.assertNoValues() - onSearchTermError.assertNoValues() - onScriptError.assertValues(R.string.please_enter_javaScript) - - verify(onDone, never()).invoke() - } - @Test fun commit_success() = runBlocking { val isLoading = viewModel.onIsLoading() .test() - val onNameError = viewModel.onNameError() - .test() - val onUrlError = viewModel.onUrlError() - .test() - val onTimeoutError = viewModel.onTimeoutError() - .test() - val onSearchTermError = viewModel.onValidationSearchTermError() - .test() - val onScriptError = viewModel.onValidationScriptError() - .test() - val onCheckIntervalError = viewModel.onCheckIntervalError() - .test() fillInModel() val onDone = mock<() -> Unit>() @@ -541,13 +302,6 @@ class ViewSiteViewModelTest { fromFinishingJob = false ) - onNameError.assertNoValues() - onUrlError.assertNoValues() - onTimeoutError.assertNoValues() - onCheckIntervalError.assertNoValues() - onSearchTermError.assertNoValues() - onScriptError.assertNoValues() - verify(onDone).invoke() } From 75297c7ff513f882ac6cc3225dc64c88c1462670 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sat, 26 Jan 2019 14:22:22 -0800 Subject: [PATCH 09/42] Fixes to vvalidator setup --- .../nocknock/ui/addsite/AddSiteActivity.kt | 43 ++++++++-------- .../nocknock/ui/viewsite/ViewSiteActivity.kt | 51 ++++++++++--------- .../retrypolicy/RetryPolicyLayout.kt | 11 +++- 3 files changed, 58 insertions(+), 47 deletions(-) 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 9713b99..e15a29f 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 @@ -117,26 +117,6 @@ class AddSiteActivity : DarkModeSwitchActivity() { viewModel.onValidationSearchTermVisibility() .toViewVisibility(this, responseValidationSearchTerm) - // Validation script - scriptInputLayout.attach( - codeData = viewModel.validationScript, - visibility = viewModel.onValidationScriptVisibility(), - form = validationForm - ) - - // Check interval - checkIntervalLayout.attach( - valueData = viewModel.checkIntervalValue, - multiplierData = viewModel.checkIntervalUnit, - form = validationForm - ) - - // Retry Policy - retryPolicyLayout.attach( - timesData = viewModel.retryPolicyTimes, - minutesData = viewModel.retryPolicyMinutes - ) - // SSL certificate sslCertificateInput.onTextChanged { viewModel.certificateUri.value = it } viewModel.certificateUri.distinct() @@ -198,7 +178,7 @@ class AddSiteActivity : DarkModeSwitchActivity() { isNotEmpty().description(R.string.please_enter_search_term) } } - input(sslCertificateInput, name = "Certificate Path") { + input(sslCertificateInput, name = "Certificate Path", optional = true) { isUri().hasScheme("file", "content") .that { it.host != null } .description(R.string.please_enter_validCertUri) @@ -210,6 +190,27 @@ class AddSiteActivity : DarkModeSwitchActivity() { } } } + + // Validation script + scriptInputLayout.attach( + codeData = viewModel.validationScript, + visibility = viewModel.onValidationScriptVisibility(), + form = validationForm + ) + + // Check interval + checkIntervalLayout.attach( + valueData = viewModel.checkIntervalValue, + multiplierData = viewModel.checkIntervalUnit, + form = validationForm + ) + + // Retry Policy + retryPolicyLayout.attach( + timesData = viewModel.retryPolicyTimes, + minutesData = viewModel.retryPolicyMinutes, + form = validationForm + ) } override fun onResume() { 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 f5f4dcc..6d131ad 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 @@ -134,26 +134,6 @@ class ViewSiteActivity : DarkModeSwitchActivity() { viewModel.onValidationSearchTermVisibility() .toViewVisibility(this, responseValidationSearchTerm) - // Validation script - scriptInputLayout.attach( - codeData = viewModel.validationScript, - visibility = viewModel.onValidationScriptVisibility(), - form = validationForm - ) - - // Check interval - checkIntervalLayout.attach( - valueData = viewModel.checkIntervalValue, - multiplierData = viewModel.checkIntervalUnit, - form = validationForm - ) - - // Retry Policy - retryPolicyLayout.attach( - timesData = viewModel.retryPolicyTimes, - minutesData = viewModel.retryPolicyMinutes - ) - // SSL certificate sslCertificateInput.onTextChanged { viewModel.certificateUri.value = it } viewModel.certificateUri.distinct() @@ -240,16 +220,16 @@ class ViewSiteActivity : DarkModeSwitchActivity() { isNotEmpty().description(R.string.please_enter_url) isUrl().description(R.string.please_enter_valid_url) } - input(responseTimeoutInput, name = "Timeout", optional = true) { - isNumber().greaterThan(0) - .description(R.string.please_enter_networkTimeout) - } input(responseValidationSearchTerm, name = "Search term") { conditional(responseValidationSearchTerm.isVisibleCondition()) { isNotEmpty().description(R.string.please_enter_search_term) } } - input(sslCertificateInput, name = "Certificate Path") { + input(responseTimeoutInput, name = "Timeout", optional = true) { + isNumber().greaterThan(0) + .description(R.string.please_enter_networkTimeout) + } + input(sslCertificateInput, name = "Certificate Path", optional = true) { isUri().hasScheme("file", "content") .that { it.host != null } .description(R.string.please_enter_validCertUri) @@ -258,6 +238,27 @@ class ViewSiteActivity : DarkModeSwitchActivity() { viewModel.commit { finish() } } } + + // Validation script + scriptInputLayout.attach( + codeData = viewModel.validationScript, + visibility = viewModel.onValidationScriptVisibility(), + form = validationForm + ) + + // Check interval + checkIntervalLayout.attach( + valueData = viewModel.checkIntervalValue, + multiplierData = viewModel.checkIntervalUnit, + form = validationForm + ) + + // Retry Policy + retryPolicyLayout.attach( + timesData = viewModel.retryPolicyTimes, + minutesData = viewModel.retryPolicyMinutes, + form = validationForm + ) } override fun onResume() { diff --git a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/retrypolicy/RetryPolicyLayout.kt b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/retrypolicy/RetryPolicyLayout.kt index 95e84d0..5a9375d 100644 --- a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/retrypolicy/RetryPolicyLayout.kt +++ b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/retrypolicy/RetryPolicyLayout.kt @@ -24,6 +24,7 @@ import com.afollestad.nocknock.viewcomponents.R import com.afollestad.nocknock.viewcomponents.ext.asSafeInt import com.afollestad.nocknock.viewcomponents.livedata.attachLiveData import com.afollestad.nocknock.viewcomponents.livedata.lifecycleOwner +import com.afollestad.vvalidator.form.Form import kotlinx.android.synthetic.main.retry_policy_layout.view.minutes import kotlinx.android.synthetic.main.retry_policy_layout.view.times import kotlinx.android.synthetic.main.retry_policy_layout.view.retry_policy_desc as description @@ -41,7 +42,8 @@ class RetryPolicyLayout( fun attach( timesData: MutableLiveData, - minutesData: MutableLiveData + minutesData: MutableLiveData, + form: Form ) { times.attachLiveData(lifecycleOwner(), timesData) minutes.attachLiveData(lifecycleOwner(), minutesData) @@ -50,6 +52,13 @@ class RetryPolicyLayout( minutes.onTextChanged { invalidateDescriptionText() } invalidateDescriptionText() + + form.input(times, optional = true) { + isNumber().greaterThan(0) + } + form.input(minutes, optional = true) { + isNumber().greaterThan(0) + } } private fun invalidateDescriptionText() { From 33388bd5c2e6acf4080f890b251158510e556e5b Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sat, 26 Jan 2019 14:27:55 -0800 Subject: [PATCH 10/42] Fixes around default SSL cert setting --- .../com/afollestad/nocknock/ui/addsite/AddSiteViewModel.kt | 2 +- .../afollestad/nocknock/ui/viewsite/ViewSiteViewModel.kt | 2 +- .../com/afollestad/nocknock/utilities/ext/StringExt.kt | 7 +++++++ .../nocknock/engine/validation/ValidationExecutor.kt | 4 +++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModel.kt b/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModel.kt index 106f232..d7d8ed5 100644 --- a/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModel.kt +++ b/app/src/main/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModel.kt @@ -153,7 +153,7 @@ class AddSiteViewModel( validationArgs = getValidationArgs(), networkTimeout = timeout, disabled = false, - certificate = certificateUri.value.toString() + certificate = certificateUri.value?.toString() ) val newLastResult = ValidationResult( diff --git a/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModel.kt b/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModel.kt index bc910b9..f41a9a7 100644 --- a/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModel.kt +++ b/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModel.kt @@ -231,7 +231,7 @@ class ViewSiteViewModel( validationArgs = getValidationArgs(), networkTimeout = timeout, disabled = false, - certificate = certificateUri.value.toString() + certificate = certificateUri.value?.toString() ) val retryPolicyTimes = retryPolicyTimes.value ?: 0 diff --git a/common/src/main/java/com/afollestad/nocknock/utilities/ext/StringExt.kt b/common/src/main/java/com/afollestad/nocknock/utilities/ext/StringExt.kt index 2fa66dc..1256a27 100644 --- a/common/src/main/java/com/afollestad/nocknock/utilities/ext/StringExt.kt +++ b/common/src/main/java/com/afollestad/nocknock/utilities/ext/StringExt.kt @@ -18,3 +18,10 @@ package com.afollestad.nocknock.utilities.ext import android.net.Uri fun String.toUri() = Uri.parse(this)!! + +fun String?.isNotNullOrEmpty(): Boolean { + if (this == null || this == "null") { + return false + } + return !isNullOrEmpty() +} diff --git a/engine/src/main/java/com/afollestad/nocknock/engine/validation/ValidationExecutor.kt b/engine/src/main/java/com/afollestad/nocknock/engine/validation/ValidationExecutor.kt index a9fb397..8ccbb1c 100644 --- a/engine/src/main/java/com/afollestad/nocknock/engine/validation/ValidationExecutor.kt +++ b/engine/src/main/java/com/afollestad/nocknock/engine/validation/ValidationExecutor.kt @@ -26,6 +26,7 @@ import com.afollestad.nocknock.data.model.Status.OK import com.afollestad.nocknock.engine.R import com.afollestad.nocknock.engine.ssl.SslManager import com.afollestad.nocknock.engine.validation.ValidationJob.Companion.KEY_SITE_ID +import com.afollestad.nocknock.utilities.ext.isNotNullOrEmpty import com.afollestad.nocknock.utilities.providers.BundleProvider import com.afollestad.nocknock.utilities.providers.JobInfoProvider import com.afollestad.nocknock.utilities.providers.StringProvider @@ -168,7 +169,7 @@ class RealValidationExecutor( return try { val clientWithTimeout = clientTimeoutChanger(okHttpClient, siteSettings.networkTimeout) - val client = if (!siteSettings.certificate.isNullOrEmpty()) { + val client = if (siteSettings.certificate.isNotNullOrEmpty()) { sslManager.clientForCertificate( certUri = siteSettings.certificate!!, siteUri = site.url, @@ -205,6 +206,7 @@ class RealValidationExecutor( ) ) } catch (ex: Exception) { + ex.printStackTrace() log("performValidation(${site.id}) = Error: ${ex.message}") CheckResult(model = site.withStatus(status = ERROR, reason = ex.message)) } From 0fbd27b54bc4217942df4d295342db11e6cb3bdd Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sat, 26 Jan 2019 14:35:34 -0800 Subject: [PATCH 11/42] Fixed some data population issues --- .../nocknock/ui/viewsite/ViewSiteActivity.kt | 14 +++++++------- .../nocknock/ui/viewsite/ViewSiteViewModelExt.kt | 14 +++++++++----- 2 files changed, 16 insertions(+), 12 deletions(-) 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 6d131ad..2aa312c 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 @@ -84,18 +84,18 @@ class ViewSiteActivity : DarkModeSwitchActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_viewsite) - setupUi() - setupValidation() - - lifecycle.run { - addObserver(viewModel) - addObserver(statusUpdateReceiver) - } // Populate view model with initial data val model = intent.getSerializableExtra(KEY_SITE) as Site viewModel.setModel(model) + setupUi() + setupValidation() + lifecycle.run { + addObserver(viewModel) + addObserver(statusUpdateReceiver) + } + // Loading loadingProgress.observe(this, viewModel.onIsLoading()) diff --git a/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModelExt.kt b/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModelExt.kt index 3864984..800f235 100644 --- a/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModelExt.kt +++ b/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModelExt.kt @@ -55,7 +55,11 @@ fun ViewSiteViewModel.setModel(site: Site) { setCheckInterval(settings.validationIntervalMs) setRetryPolicy(site.retryPolicy) headers.value = site.headers - certificateUri.value = settings.certificate + if (settings.certificate == "null") { + certificateUri.value = "" + } else { + certificateUri.value = settings.certificate + } this.disabled.value = settings.disabled this.lastResult.value = site.lastResult @@ -65,22 +69,22 @@ private fun ViewSiteViewModel.setCheckInterval(interval: Long) { when { interval >= WEEK -> { checkIntervalValue.value = - getIntervalFromUnit(interval, WEEK) + getIntervalFromUnit(interval, WEEK) checkIntervalUnit.value = WEEK } interval >= DAY -> { checkIntervalValue.value = - getIntervalFromUnit(interval, DAY) + getIntervalFromUnit(interval, DAY) checkIntervalUnit.value = DAY } interval >= HOUR -> { checkIntervalValue.value = - getIntervalFromUnit(interval, HOUR) + getIntervalFromUnit(interval, HOUR) checkIntervalUnit.value = HOUR } interval >= MINUTE -> { checkIntervalValue.value = - getIntervalFromUnit(interval, MINUTE) + getIntervalFromUnit(interval, MINUTE) checkIntervalUnit.value = MINUTE } else -> { From de59bf9ec1643362b9258ec2bc284b0ed75d4d54 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sat, 26 Jan 2019 14:41:02 -0800 Subject: [PATCH 12/42] 0.8.6 --- .idea/misc.xml | 2 +- dependencies.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 9d1e235..50f0406 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -40,7 +40,7 @@ - + diff --git a/dependencies.gradle b/dependencies.gradle index fd28b7d..76736c1 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -3,8 +3,8 @@ ext.versions = [ minSdk : 21, compileSdk : 28, buildTools : '28.0.3', - publishVersion : '0.8.5', - publishVersionCode : 39, + publishVersion : '0.8.6', + publishVersionCode : 40, // Plugins gradlePlugin : '3.3.0', From 3e5b1d4d8edcc7aee71f169b90d715a164d2fc7a Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sat, 26 Jan 2019 14:55:06 -0800 Subject: [PATCH 13/42] Resolve two crashes --- .../engine/validation/ValidationExecutor.kt | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/engine/src/main/java/com/afollestad/nocknock/engine/validation/ValidationExecutor.kt b/engine/src/main/java/com/afollestad/nocknock/engine/validation/ValidationExecutor.kt index 8ccbb1c..d47d616 100644 --- a/engine/src/main/java/com/afollestad/nocknock/engine/validation/ValidationExecutor.kt +++ b/engine/src/main/java/com/afollestad/nocknock/engine/validation/ValidationExecutor.kt @@ -36,6 +36,7 @@ import okhttp3.Response import org.jetbrains.annotations.TestOnly import java.net.SocketTimeoutException import java.util.concurrent.TimeUnit.MILLISECONDS +import kotlin.math.max import timber.log.Timber.d as log /** @author Aidan Follestad (@afollestad) */ @@ -154,21 +155,23 @@ class RealValidationExecutor( check(site.id != 0L) { "Cannot schedule validations for jobs with no ID." } val siteSettings = site.settings requireNotNull(siteSettings) { "Site settings must be populated." } - check(siteSettings.networkTimeout > 0) { "Network timeout not set for site ${site.id}" } log("performValidation(${site.id}) - GET ${site.url}") val request = Request.Builder() .apply { url(site.url) get() - site.headers.forEach { header -> - addHeader(header.key, header.value) - } + site.headers + .filter { header -> header.key.isNotNullOrEmpty() } + .forEach { header -> + addHeader(header.key, header.value) + } } .build() return try { - val clientWithTimeout = clientTimeoutChanger(okHttpClient, siteSettings.networkTimeout) + val timeout = max(siteSettings.networkTimeout, 1) + val clientWithTimeout = clientTimeoutChanger(okHttpClient, timeout) val client = if (siteSettings.certificate.isNotNullOrEmpty()) { sslManager.clientForCertificate( certUri = siteSettings.certificate!!, From 9514a5ec83c585e0e76c1478f5f14ba899ae495a Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sat, 26 Jan 2019 14:55:26 -0800 Subject: [PATCH 14/42] 0.8.6b --- .idea/misc.xml | 2 +- dependencies.gradle | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 50f0406..9d1e235 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -40,7 +40,7 @@ - + diff --git a/dependencies.gradle b/dependencies.gradle index 76736c1..f549cb5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -3,8 +3,8 @@ ext.versions = [ minSdk : 21, compileSdk : 28, buildTools : '28.0.3', - publishVersion : '0.8.6', - publishVersionCode : 40, + publishVersion : '0.8.6b', + publishVersionCode : 41, // Plugins gradlePlugin : '3.3.0', From e39093b5268ba68f32be870678945894a9e51d04 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sat, 26 Jan 2019 18:41:55 -0800 Subject: [PATCH 15/42] Fix script input layout background color --- app/src/main/res/layout/activity_addsite.xml | 2 +- app/src/main/res/layout/activity_viewsite.xml | 2 +- app/src/main/res/values/attrs.xml | 1 + app/src/main/res/values/colors.xml | 4 +++- app/src/main/res/values/styles.xml | 2 +- app/src/main/res/values/styles_parents.xml | 2 ++ .../nocknock/viewcomponents/ext/ViewExt.kt | 13 ------------- .../viewcomponents/js/JavaScriptInputLayout.kt | 2 +- 8 files changed, 10 insertions(+), 18 deletions(-) diff --git a/app/src/main/res/layout/activity_addsite.xml b/app/src/main/res/layout/activity_addsite.xml index f7bd3e8..80f83da 100644 --- a/app/src/main/res/layout/activity_addsite.xml +++ b/app/src/main/res/layout/activity_addsite.xml @@ -123,7 +123,7 @@ android:layout_height="wrap_content" android:layout_marginBottom="@dimen/content_inset" android:layout_marginTop="@dimen/content_inset_half" - android:background="@color/lighterGray" + android:background="?scriptLayoutBackground" /> + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index d69b862..f840cee 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -7,7 +7,9 @@ #212121 #252525 - #303030 + #303030 + #EEEEEE + #FF6E40 #E44615 #40FF6E40 diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 1cb4a89..e4b435a 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -6,7 +6,7 @@ diff --git a/app/src/main/res/values/styles_parents.xml b/app/src/main/res/values/styles_parents.xml index decbdb8..dc5e3d6 100644 --- a/app/src/main/res/values/styles_parents.xml +++ b/app/src/main/res/values/styles_parents.xml @@ -9,6 +9,7 @@ #000000 #EEEEEE #000000 + @color/lighterGray #212121 #727272 @@ -33,6 +34,7 @@ #ffffff #303030 #FFFFFF + @color/darkerGray #FFFFFF #F0F0F0 diff --git a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/ext/ViewExt.kt b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/ext/ViewExt.kt index 445c931..e543863 100644 --- a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/ext/ViewExt.kt +++ b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/ext/ViewExt.kt @@ -18,7 +18,6 @@ package com.afollestad.nocknock.viewcomponents.ext import android.view.View import android.view.View.GONE import android.view.View.VISIBLE -import android.view.ViewTreeObserver import androidx.annotation.DimenRes import com.afollestad.vvalidator.form.Condition @@ -32,18 +31,6 @@ fun View.hide() { fun View.showOrHide(show: Boolean) = if (show) show() else hide() -fun View.onLayout(cb: () -> Unit) { - if (this.viewTreeObserver.isAlive) { - this.viewTreeObserver.addOnGlobalLayoutListener( - object : ViewTreeObserver.OnGlobalLayoutListener { - override fun onGlobalLayout() { - cb() - this@onLayout.viewTreeObserver.removeOnGlobalLayoutListener(this) - } - }) - } -} - fun View.dimenFloat(@DimenRes res: Int) = resources.getDimension(res) fun View.dimenInt(@DimenRes res: Int) = resources.getDimensionPixelSize(res) diff --git a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/js/JavaScriptInputLayout.kt b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/js/JavaScriptInputLayout.kt index 176f32d..1b1a29f 100644 --- a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/js/JavaScriptInputLayout.kt +++ b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/js/JavaScriptInputLayout.kt @@ -52,7 +52,7 @@ class JavaScriptInputLayout( contentInset // bottom ) elevation = dimenFloat(dimen.default_elevation) - inflate(context, layout.javascript_input_layout, this) + inflate(context, R.layout.javascript_input_layout, this) } fun attach( From 68b6944542e6c76f91db0c2e4ec79ca394caa2be Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sat, 26 Jan 2019 18:42:16 -0800 Subject: [PATCH 16/42] 0.8.6c --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index f549cb5..a1a5881 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -3,8 +3,8 @@ ext.versions = [ minSdk : 21, compileSdk : 28, buildTools : '28.0.3', - publishVersion : '0.8.6b', - publishVersionCode : 41, + publishVersion : '0.8.6c', + publishVersionCode : 42, // Plugins gradlePlugin : '3.3.0', From 7f507792a85780099debcbc39e3a16ef0707df84 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Wed, 30 Jan 2019 13:53:10 -0800 Subject: [PATCH 17/42] Update gradle-wrapper.properties --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8ab96fb..2128899 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip From 872e99d80dd2e17e5812f8b1fd8323b635b6b84c Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Fri, 1 Feb 2019 15:21:11 -0800 Subject: [PATCH 18/42] Custom repo not needed anymore for Material Dialogs --- build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/build.gradle b/build.gradle index d99c0ee..a8d8d73 100644 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,6 @@ allprojects { repositories { google() jcenter() - maven { url "https://dl.bintray.com/drummer-aidan/maven" } maven { url "https://jitpack.io" } } From ef18464728ce07661b75fa731106d5c052c08285 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Fri, 1 Feb 2019 17:57:23 -0800 Subject: [PATCH 19/42] vvalidator 0.3.0 --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index a1a5881..4daddb4 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -36,7 +36,7 @@ ext.versions = [ // afollestad materialDialogs : '2.0.0-rc9', rxkPrefs : '1.2.2', - vvalidator : '0.2.2', + vvalidator : '0.3.0', // Debugging timber : '4.7.1', From 6d382b93a5725e69c3ae5dd2b29916db9a279708 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 21 Feb 2019 14:43:04 -0800 Subject: [PATCH 20/42] Dependency updates --- dependencies.gradle | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 4daddb4..f0f8eb2 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -7,17 +7,17 @@ ext.versions = [ publishVersionCode : 42, // Plugins - gradlePlugin : '3.3.0', - spotlessPlugin : '3.17.0', + gradlePlugin : '3.3.1', + spotlessPlugin : '3.18.0', versionPlugin : '0.20.0', fabricPlugin : '1.+', // Misc - okHttp : '3.12.1', + okHttp : '3.13.1', rhino : '1.7.10', // Kotlin - kotlin : '1.3.20', + kotlin : '1.3.21', coroutines : '1.1.1', koin : '1.0.2', @@ -34,17 +34,17 @@ ext.versions = [ rxBinding : '3.0.0-alpha1', // afollestad - materialDialogs : '2.0.0-rc9', - rxkPrefs : '1.2.2', - vvalidator : '0.3.0', + materialDialogs : '2.0.0', + rxkPrefs : '1.2.4', + vvalidator : '0.3.1', // Debugging timber : '4.7.1', - fabric : '2.9.8@aar', + fabric : '2.9.9@aar', // Unit testing junit : '4.12', - mockito : '2.23.4', + mockito : '2.24.5', mockitoKotlin : '2.1.0', truth : '0.42', From 334e9e823c3edaa8261af139bb610676deb45143 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 14 Mar 2019 13:55:19 -0700 Subject: [PATCH 21/42] Switch to Firebase for Crashlytics --- .gitignore | 4 +- .idea/misc.xml | 2 +- app/build.gradle | 20 ++++----- .../com/afollestad/nocknock/NockNockApp.kt | 6 +-- build.gradle | 1 + common/build.gradle | 1 + dependencies.gradle | 21 ++++++---- fabric.gradle | 29 ------------- gradle.properties | 3 ++ mock/mock-google-services.json | 42 +++++++++++++++++++ mock/mock.gradle | 13 ++++++ 11 files changed, 87 insertions(+), 55 deletions(-) delete mode 100644 fabric.gradle create mode 100644 mock/mock-google-services.json create mode 100644 mock/mock.gradle diff --git a/.gitignore b/.gitignore index 161128f..454e51a 100644 --- a/.gitignore +++ b/.gitignore @@ -180,4 +180,6 @@ gradle-app.setting .gradletasknamecache # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 -# gradle/wrapper/gradle-wrapper.properties \ No newline at end of file +# gradle/wrapper/gradle-wrapper.properties + +app/google-services.json \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 9d1e235..50f0406 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -40,7 +40,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index efff452..4b02af4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -4,8 +4,6 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-android-extensions' -apply from: '../fabric.gradle' - android { compileSdkVersion versions.compileSdk buildToolsVersion versions.buildTools @@ -18,14 +16,9 @@ android { versionName versions.publishVersion } - buildTypes { - debug { - ext.enableCrashlytics = false - buildConfigField "String", "FABRIC_API_KEY", "\"\"" - } - release { - buildConfigField "String", "FABRIC_API_KEY", "\"${getFabricApiKey()}\"" - } + compileOptions { + sourceCompatibility 1.8 + targetCompatibility 1.8 } } @@ -41,6 +34,7 @@ dependencies { implementation 'androidx.recyclerview:recyclerview:' + versions.androidxRecyclerView implementation 'com.google.android.material:material:' + versions.googleMaterial implementation 'androidx.browser:browser:' + versions.androidxBrowser + implementation 'com.google.firebase:firebase-core:' + versions.firebaseCore // Lifecycle kapt 'androidx.lifecycle:lifecycle-compiler:' + versions.lifecycle @@ -74,4 +68,8 @@ dependencies { androidTestImplementation 'androidx.test:rules:' + versions.androidxTestRunner } -apply from: '../spotless.gradle' \ No newline at end of file +apply from: '../spotless.gradle' +apply from: '../mock/mock.gradle' + +apply plugin: "io.fabric" +apply plugin: 'com.google.gms.google-services' \ No newline at end of file diff --git a/app/src/main/java/com/afollestad/nocknock/NockNockApp.kt b/app/src/main/java/com/afollestad/nocknock/NockNockApp.kt index 2cd0af3..3c29301 100644 --- a/app/src/main/java/com/afollestad/nocknock/NockNockApp.kt +++ b/app/src/main/java/com/afollestad/nocknock/NockNockApp.kt @@ -47,10 +47,8 @@ class NockNockApp : Application() { Timber.plant(DebugTree()) } - if (BuildConfig.FABRIC_API_KEY.isNotEmpty()) { - Timber.plant(FabricTree()) - Fabric.with(this, Crashlytics()) - } + Timber.plant(FabricTree()) + Fabric.with(this, Crashlytics()) val modules = listOf( prefModule, diff --git a/build.gradle b/build.gradle index a8d8d73..2d8e462 100644 --- a/build.gradle +++ b/build.gradle @@ -15,6 +15,7 @@ buildscript { classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:' + versions.kotlin classpath 'com.github.ben-manes:gradle-versions-plugin:' + versions.versionPlugin classpath 'io.fabric.tools:gradle:' + versions.fabricPlugin + classpath 'com.google.gms:google-services:' + versions.googleServices } } diff --git a/common/build.gradle b/common/build.gradle index 8472928..76d7d02 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -30,6 +30,7 @@ dependencies { implementation 'org.mozilla:rhino:' + versions.rhino api 'com.afollestad:rxkprefs:' + versions.rxkPrefs + api "io.reactivex.rxjava2:rxjava:" + versions.rxJava testImplementation 'junit:junit:' + versions.junit testImplementation 'com.google.truth:truth:' + versions.truth diff --git a/dependencies.gradle b/dependencies.gradle index f0f8eb2..fd4a5ef 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -7,13 +7,14 @@ ext.versions = [ publishVersionCode : 42, // Plugins - gradlePlugin : '3.3.1', - spotlessPlugin : '3.18.0', - versionPlugin : '0.20.0', + gradlePlugin : '3.3.2', + spotlessPlugin : '3.19.0', + versionPlugin : '0.21.0', + googleServices : '4.2.0', fabricPlugin : '1.+', // Misc - okHttp : '3.13.1', + okHttp : '3.14.0', rhino : '1.7.10', // Kotlin @@ -22,20 +23,22 @@ ext.versions = [ koin : '1.0.2', // Google/AndroidX - androidxAnnotations : '1.0.1', + androidxAnnotations : '1.0.2', androidxCore : '1.0.2', androidxRecyclerView: '1.0.0', androidxBrowser : '1.0.0', googleMaterial : '1.0.0', room : '2.0.0', lifecycle : '2.0.0', + firebaseCore : '16.0.7', // Rx + rxJava : '2.2.7', rxBinding : '3.0.0-alpha1', // afollestad - materialDialogs : '2.0.0', - rxkPrefs : '1.2.4', + materialDialogs : '2.0.3', + rxkPrefs : '1.2.5', vvalidator : '0.3.1', // Debugging @@ -44,9 +47,9 @@ ext.versions = [ // Unit testing junit : '4.12', - mockito : '2.24.5', + mockito : '2.25.0', mockitoKotlin : '2.1.0', - truth : '0.42', + truth : '0.43', // UI testing androidxTestRunner : '1.1.1', diff --git a/fabric.gradle b/fabric.gradle deleted file mode 100644 index 315dff2..0000000 --- a/fabric.gradle +++ /dev/null @@ -1,29 +0,0 @@ -apply plugin: 'io.fabric' - -ext.getFabricApiKey = { - return System.getenv('FABRIC_APIKEY') ?: "xxxe76c4xxxx97e8cxxxx0135e9d46f5a2xxx" -} - -ext.getFabricApiSecret = { - return System.getenv('FABRIC_APISECRET') ?: "xx68f6074dxxxxxc11dxxx97c172e8ebf0" -} - -def buildFabricProperties() { - def propertiesFile = file("fabric.properties") - def apiSecret = getFabricApiSecret() - def apiKey = getFabricApiKey() - - if (propertiesFile.exists()) { - propertiesFile.delete() - } - - def commentMessage = "suppress inspection \"UnusedProperty\" for whole file" - ant.propertyfile(file: "fabric.properties", comment: commentMessage) { - entry(key: "apiSecret", value: apiSecret) - entry(key: "apiKey", value: apiKey) - } -} - -afterEvaluate { - buildFabricProperties() -} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 9516cf5..c62d03d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,3 +16,6 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryErro # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true + +android.useAndroidX=true +android.enableJetifier=true diff --git a/mock/mock-google-services.json b/mock/mock-google-services.json new file mode 100644 index 0000000..d9866d8 --- /dev/null +++ b/mock/mock-google-services.json @@ -0,0 +1,42 @@ +{ + "project_info": { + "project_number": "123456789000", + "firebase_url": "https://mockproject-1234.firebaseio.com", + "project_id": "mockproject-1234", + "storage_bucket": "mockproject-1234.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:123456789000:android:f1bf012572b04063", + "android_client_info": { + "package_name": "com.afollestad.nocknock" + } + }, + "oauth_client": [ + { + "client_id": "123456789000-hjugbg6ud799v4c49dim8ce2usclthar.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzbSzCn1N6LWIe6wthYyrgUUSAlUsdqMb-wvTo" + } + ], + "services": { + "analytics_service": { + "status": 1 + }, + "appinvite_service": { + "status": 1, + "other_platform_oauth_client": [] + }, + "ads_service": { + "status": 2 + } + } + } + ], + "configuration_version": "1" +} diff --git a/mock/mock.gradle b/mock/mock.gradle new file mode 100644 index 0000000..2fa58ef --- /dev/null +++ b/mock/mock.gradle @@ -0,0 +1,13 @@ +// This script must be applied in app/build.gradle for the paths here to work correctly + +def copyMockFilesNeeded() { + def srcGoogleServicesFile = file("../mock/mock-google-services.json") + def destGoogleServicesFile = file("google-services.json") + if (!destGoogleServicesFile.exists()) { + destGoogleServicesFile.write(srcGoogleServicesFile.text) + } +} + +afterEvaluate { + copyMockFilesNeeded() +} \ No newline at end of file From 4da8cb5f1174187e2421a6499114a6213ee2d41d Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 14 Mar 2019 15:01:24 -0700 Subject: [PATCH 22/42] Fix tests --- .../nocknock/ui/DarkModeSwitchActivity.kt | 33 +++++++++++++++---- .../com/afollestad/nocknock/ui/NightMode.kt | 11 +++++++ .../nocknock/ui/main/MainActivity.kt | 9 ++++- .../nocknock/ui/viewsite/ViewSiteViewModel.kt | 2 +- .../ui/addsite/AddSiteViewModelTest.kt | 19 ++++++++--- .../ui/viewsite/ViewSiteViewModelTest.kt | 20 ++++++++++- .../com/afollestad/nocknock/data/TestUtil.kt | 3 +- 7 files changed, 82 insertions(+), 15 deletions(-) create mode 100644 app/src/main/java/com/afollestad/nocknock/ui/NightMode.kt diff --git a/app/src/main/java/com/afollestad/nocknock/ui/DarkModeSwitchActivity.kt b/app/src/main/java/com/afollestad/nocknock/ui/DarkModeSwitchActivity.kt index c43b729..5785fd3 100644 --- a/app/src/main/java/com/afollestad/nocknock/ui/DarkModeSwitchActivity.kt +++ b/app/src/main/java/com/afollestad/nocknock/ui/DarkModeSwitchActivity.kt @@ -15,10 +15,15 @@ */ package com.afollestad.nocknock.ui +import android.content.res.Configuration +import android.os.Build import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import com.afollestad.nocknock.R import com.afollestad.nocknock.koin.PREF_DARK_MODE +import com.afollestad.nocknock.ui.NightMode.DISABLED +import com.afollestad.nocknock.ui.NightMode.ENABLED +import com.afollestad.nocknock.ui.NightMode.UNKNOWN import com.afollestad.nocknock.utilities.rx.attachLifecycle import com.afollestad.rxkprefs.Pref import org.koin.android.ext.android.inject @@ -35,13 +40,27 @@ abstract class DarkModeSwitchActivity : AppCompatActivity() { setTheme(themeRes()) super.onCreate(savedInstanceState) - darkModePref.observe() - .filter { it != isDarkModeEnabled } - .subscribe { - log("Theme changed, recreating Activity.") - recreate() - } - .attachLifecycle(this) + if (getCurrentNightMode() == UNKNOWN) { + darkModePref.observe() + .filter { it != isDarkModeEnabled } + .subscribe { + log("Theme changed, recreating Activity.") + recreate() + } + .attachLifecycle(this) + } + } + + protected fun getCurrentNightMode(): NightMode { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { + return UNKNOWN + } + val currentNightMode = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK + return when (currentNightMode) { + Configuration.UI_MODE_NIGHT_YES -> return ENABLED + Configuration.UI_MODE_NIGHT_NO -> return DISABLED + else -> UNKNOWN + } } protected fun isDarkMode() = darkModePref.get() diff --git a/app/src/main/java/com/afollestad/nocknock/ui/NightMode.kt b/app/src/main/java/com/afollestad/nocknock/ui/NightMode.kt new file mode 100644 index 0000000..fdbbcc2 --- /dev/null +++ b/app/src/main/java/com/afollestad/nocknock/ui/NightMode.kt @@ -0,0 +1,11 @@ +package com.afollestad.nocknock.ui + +/** @author Aidan Follestad (@afollestad) */ +enum class NightMode { + /** Night mode is on at the system level. */ + ENABLED, + /** Night mode is off at the system level. */ + DISABLED, + /** We don't know about night mode, fallback to custom impl. */ + UNKNOWN +} \ No newline at end of file diff --git a/app/src/main/java/com/afollestad/nocknock/ui/main/MainActivity.kt b/app/src/main/java/com/afollestad/nocknock/ui/main/MainActivity.kt index bd7796c..75647e2 100644 --- a/app/src/main/java/com/afollestad/nocknock/ui/main/MainActivity.kt +++ b/app/src/main/java/com/afollestad/nocknock/ui/main/MainActivity.kt @@ -33,6 +33,7 @@ import com.afollestad.nocknock.data.model.Site import com.afollestad.nocknock.dialogs.AboutDialog import com.afollestad.nocknock.notifications.NockNotificationManager import com.afollestad.nocknock.ui.DarkModeSwitchActivity +import com.afollestad.nocknock.ui.NightMode.UNKNOWN import com.afollestad.nocknock.utilities.providers.IntentProvider import com.afollestad.nocknock.utilities.ui.toast import com.afollestad.nocknock.viewUrl @@ -93,7 +94,13 @@ class MainActivity : DarkModeSwitchActivity() { toolbar.run { inflateMenu(R.menu.menu_main) menu.findItem(R.id.dark_mode) - .isChecked = isDarkMode() + .apply { + if (getCurrentNightMode() == UNKNOWN) { + isVisible = false + } else { + isChecked = isDarkMode() + } + } setOnMenuItemClickListener { item -> when (item.itemId) { R.id.about -> AboutDialog.show(this@MainActivity) diff --git a/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModel.kt b/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModel.kt index f41a9a7..b5c9f93 100644 --- a/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModel.kt +++ b/app/src/main/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModel.kt @@ -223,7 +223,7 @@ class ViewSiteViewModel( private fun getUpdatedDbModel(): Site? { val timeout = timeout.value ?: 10_000 - val cleanedTags = tags.value?.split(',')?.joinToString { it.trim() } ?: "" + val cleanedTags = tags.value?.split(',')?.joinToString(separator = ",") ?: "" val newSettings = site.settings!!.copy( validationIntervalMs = getCheckIntervalMs(), diff --git a/app/src/test/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModelTest.kt b/app/src/test/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModelTest.kt index b62f9a6..1319310 100644 --- a/app/src/test/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModelTest.kt +++ b/app/src/test/java/com/afollestad/nocknock/ui/addsite/AddSiteViewModelTest.kt @@ -17,20 +17,21 @@ package com.afollestad.nocknock.ui.addsite import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.afollestad.nocknock.R +import com.afollestad.nocknock.data.model.Header import com.afollestad.nocknock.data.model.Site import com.afollestad.nocknock.data.model.SiteSettings +import com.afollestad.nocknock.data.model.Status.WAITING import com.afollestad.nocknock.data.model.ValidationMode.JAVASCRIPT import com.afollestad.nocknock.data.model.ValidationMode.STATUS_CODE import com.afollestad.nocknock.data.model.ValidationMode.TERM_SEARCH +import com.afollestad.nocknock.data.model.ValidationResult import com.afollestad.nocknock.engine.validation.ValidationExecutor import com.afollestad.nocknock.mockDatabase import com.afollestad.nocknock.utilities.ext.MINUTE import com.afollestad.nocknock.utilities.livedata.test import com.google.common.truth.Truth.assertThat -import com.nhaarman.mockitokotlin2.any import com.nhaarman.mockitokotlin2.argumentCaptor import com.nhaarman.mockitokotlin2.mock -import com.nhaarman.mockitokotlin2.never import com.nhaarman.mockitokotlin2.verify import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -159,19 +160,24 @@ class AddSiteViewModelTest { val siteCaptor = argumentCaptor() val settingsCaptor = argumentCaptor() + val validationResultCaptor = argumentCaptor() isLoading.assertValues(true, false) verify(database.siteDao()).insert(siteCaptor.capture()) verify(database.siteSettingsDao()).insert(settingsCaptor.capture()) - verify(database.validationResultsDao(), never()).insert(any()) + verify(database.validationResultsDao()).insert(validationResultCaptor.capture()) val settings = settingsCaptor.firstValue + val result = validationResultCaptor.firstValue.copy(siteId = 1) val model = siteCaptor.firstValue.copy( id = 1, // fill it in because our insert captor doesn't catch this settings = settings, - lastResult = null + lastResult = result ) + assertThat(result.reason).isNull() + assertThat(result.status).isEqualTo(WAITING) + verify(validationManager).scheduleValidation( site = model, rightNow = true, @@ -191,5 +197,10 @@ class AddSiteViewModelTest { validationScript.value = null checkIntervalValue.value = 60 checkIntervalUnit.value = 1000 + tags.value = "one,two" + headers.value = listOf( + Header(2L, 1L, key = "Content-Type", value = "text/html"), + Header(3L, 1L, key = "User-Agent", value = "NockNock") + ) } } diff --git a/app/src/test/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModelTest.kt b/app/src/test/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModelTest.kt index d7bc8a8..47fe6e0 100644 --- a/app/src/test/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModelTest.kt +++ b/app/src/test/java/com/afollestad/nocknock/ui/viewsite/ViewSiteViewModelTest.kt @@ -18,6 +18,8 @@ package com.afollestad.nocknock.ui.viewsite import androidx.arch.core.executor.testing.InstantTaskExecutorRule import com.afollestad.nocknock.MOCK_MODEL_1 import com.afollestad.nocknock.R +import com.afollestad.nocknock.data.model.Header +import com.afollestad.nocknock.data.model.RetryPolicy import com.afollestad.nocknock.data.model.Site import com.afollestad.nocknock.data.model.SiteSettings import com.afollestad.nocknock.data.model.Status.CHECKING @@ -29,6 +31,7 @@ import com.afollestad.nocknock.data.model.ValidationMode.STATUS_CODE import com.afollestad.nocknock.data.model.ValidationMode.TERM_SEARCH import com.afollestad.nocknock.data.model.ValidationResult import com.afollestad.nocknock.engine.validation.ValidationExecutor +import com.afollestad.nocknock.fakeRetryPolicy import com.afollestad.nocknock.mockDatabase import com.afollestad.nocknock.notifications.NockNotificationManager import com.afollestad.nocknock.utilities.livedata.test @@ -38,8 +41,10 @@ import com.google.common.truth.Truth.assertThat import com.nhaarman.mockitokotlin2.any import com.nhaarman.mockitokotlin2.argumentCaptor import com.nhaarman.mockitokotlin2.doAnswer +import com.nhaarman.mockitokotlin2.doReturn import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.verify +import com.nhaarman.mockitokotlin2.whenever import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking @@ -255,6 +260,8 @@ class ViewSiteViewModelTest { } @Test fun commit_success() = runBlocking { + whenever(database.retryPolicyDao().forSite(any())).doReturn(listOf(fakeRetryPolicy(1))) + val isLoading = viewModel.onIsLoading() .test() @@ -267,11 +274,13 @@ class ViewSiteViewModelTest { val siteCaptor = argumentCaptor() val settingsCaptor = argumentCaptor() val resultCaptor = argumentCaptor() + val retryPolicyCaptor = argumentCaptor() isLoading.assertValues(true, false) verify(database.siteDao()).update(siteCaptor.capture()) verify(database.siteSettingsDao()).update(settingsCaptor.capture()) verify(database.validationResultsDao()).update(resultCaptor.capture()) + verify(database.retryPolicyDao()).update(retryPolicyCaptor.capture()) // From fillInModel() below val updatedSettings = MOCK_MODEL_1.settings!!.copy( @@ -284,11 +293,13 @@ class ViewSiteViewModelTest { val updatedResult = MOCK_MODEL_1.lastResult!!.copy( status = WAITING ) + val retryPolicy = retryPolicyCaptor.firstValue val updatedModel = MOCK_MODEL_1.copy( name = "Hello There", url = "https://www.hellothere.com", settings = updatedSettings, - lastResult = updatedResult + lastResult = updatedResult, + retryPolicy = retryPolicy ) assertThat(siteCaptor.firstValue).isEqualTo(updatedModel) @@ -373,5 +384,12 @@ class ViewSiteViewModelTest { validationScript.value = "throw 'Oh no!'" checkIntervalValue.value = 24 checkIntervalUnit.value = 60000 + tags.value = "one,two" + retryPolicyTimes.value = 5 + retryPolicyMinutes.value = 5 + headers.value = listOf( + Header(2L, 1L, key = "Content-Type", value = "text/html"), + Header(3L, 1L, key = "User-Agent", value = "NockNock") + ) } } diff --git a/data/src/androidTest/java/com/afollestad/nocknock/data/TestUtil.kt b/data/src/androidTest/java/com/afollestad/nocknock/data/TestUtil.kt index 6fc9796..2866b50 100644 --- a/data/src/androidTest/java/com/afollestad/nocknock/data/TestUtil.kt +++ b/data/src/androidTest/java/com/afollestad/nocknock/data/TestUtil.kt @@ -35,7 +35,8 @@ fun fakeSettingsModel( validationMode = validationMode, validationArgs = null, disabled = false, - networkTimeout = 10000 + networkTimeout = 10000, + certificate = null ) fun fakeResultModel( From df2652860e51ac171ad56ac507de4a64c2a7a1c0 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 14 Mar 2019 15:06:03 -0700 Subject: [PATCH 23/42] -am --- .../nocknock/ui/DarkModeSwitchActivity.kt | 8 +++++++- .../com/afollestad/nocknock/ui/NightMode.kt | 17 ++++++++++++++++- .../afollestad/nocknock/ui/main/MainActivity.kt | 4 ++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/afollestad/nocknock/ui/DarkModeSwitchActivity.kt b/app/src/main/java/com/afollestad/nocknock/ui/DarkModeSwitchActivity.kt index 5785fd3..bf5422d 100644 --- a/app/src/main/java/com/afollestad/nocknock/ui/DarkModeSwitchActivity.kt +++ b/app/src/main/java/com/afollestad/nocknock/ui/DarkModeSwitchActivity.kt @@ -63,7 +63,13 @@ abstract class DarkModeSwitchActivity : AppCompatActivity() { } } - protected fun isDarkMode() = darkModePref.get() + protected fun isDarkMode(): Boolean { + return when (getCurrentNightMode()) { + ENABLED -> true + DISABLED -> false + else -> darkModePref.get() + } + } protected fun toggleDarkMode() = setDarkMode(!isDarkMode()) diff --git a/app/src/main/java/com/afollestad/nocknock/ui/NightMode.kt b/app/src/main/java/com/afollestad/nocknock/ui/NightMode.kt index fdbbcc2..2930fea 100644 --- a/app/src/main/java/com/afollestad/nocknock/ui/NightMode.kt +++ b/app/src/main/java/com/afollestad/nocknock/ui/NightMode.kt @@ -1,3 +1,18 @@ +/** + * Designed and developed by Aidan Follestad (@afollestad) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.afollestad.nocknock.ui /** @author Aidan Follestad (@afollestad) */ @@ -8,4 +23,4 @@ enum class NightMode { DISABLED, /** We don't know about night mode, fallback to custom impl. */ UNKNOWN -} \ No newline at end of file +} diff --git a/app/src/main/java/com/afollestad/nocknock/ui/main/MainActivity.kt b/app/src/main/java/com/afollestad/nocknock/ui/main/MainActivity.kt index 75647e2..7b59bf1 100644 --- a/app/src/main/java/com/afollestad/nocknock/ui/main/MainActivity.kt +++ b/app/src/main/java/com/afollestad/nocknock/ui/main/MainActivity.kt @@ -96,9 +96,9 @@ class MainActivity : DarkModeSwitchActivity() { menu.findItem(R.id.dark_mode) .apply { if (getCurrentNightMode() == UNKNOWN) { - isVisible = false - } else { isChecked = isDarkMode() + } else { + isVisible = false } } setOnMenuItemClickListener { item -> From 8c3654c4ac9e056e3ae5a9e192c9db735a16b814 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 14 Mar 2019 15:06:38 -0700 Subject: [PATCH 24/42] 0.8.7 --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index fd4a5ef..4225186 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -3,8 +3,8 @@ ext.versions = [ minSdk : 21, compileSdk : 28, buildTools : '28.0.3', - publishVersion : '0.8.6c', - publishVersionCode : 42, + publishVersion : '0.8.7', + publishVersionCode : 43, // Plugins gradlePlugin : '3.3.2', From b26543d24406f1290a66d10afdfd8787644ba363 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Sat, 16 Mar 2019 12:08:29 -0700 Subject: [PATCH 25/42] Update dependencies.gradle --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 4225186..514e186 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -37,7 +37,7 @@ ext.versions = [ rxBinding : '3.0.0-alpha1', // afollestad - materialDialogs : '2.0.3', + materialDialogs : '2.1.0', rxkPrefs : '1.2.5', vvalidator : '0.3.1', From 997c797598b803dff6df22aaeed0f2b7af82f56a Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 11 Apr 2019 12:56:23 -0700 Subject: [PATCH 26/42] Kotlin 1.3.30 --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index 514e186..71e118a 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -18,7 +18,7 @@ ext.versions = [ rhino : '1.7.10', // Kotlin - kotlin : '1.3.21', + kotlin : '1.3.30', coroutines : '1.1.1', koin : '1.0.2', From 9ea9c780999a3f85ada5baf5ec81c759f960a0ff Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Mon, 15 Apr 2019 20:37:35 -0700 Subject: [PATCH 27/42] Add privacy policy link to the about dialog --- app/src/main/res/values/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2267417..2fe7796 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,6 +14,7 @@ LinkedIn

Nock Nock is open source! Check out the GitHub page!
Icon by Kevin Aguilar of 221 Pixels. +
View the Privacy Policy. ]]> Dark Mode From 1ccb89bfc374f0c6b304a07052e881af58476a29 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Mon, 15 Apr 2019 20:46:36 -0700 Subject: [PATCH 28/42] Dependency upgrades --- dependencies.gradle | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 71e118a..68f0e24 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -8,18 +8,18 @@ ext.versions = [ // Plugins gradlePlugin : '3.3.2', - spotlessPlugin : '3.19.0', + spotlessPlugin : '3.22.0', versionPlugin : '0.21.0', googleServices : '4.2.0', fabricPlugin : '1.+', // Misc - okHttp : '3.14.0', + okHttp : '3.14.1', rhino : '1.7.10', // Kotlin kotlin : '1.3.30', - coroutines : '1.1.1', + coroutines : '1.2.0', koin : '1.0.2', // Google/AndroidX @@ -30,16 +30,16 @@ ext.versions = [ googleMaterial : '1.0.0', room : '2.0.0', lifecycle : '2.0.0', - firebaseCore : '16.0.7', + firebaseCore : '16.0.8', // Rx - rxJava : '2.2.7', + rxJava : '2.2.8', rxBinding : '3.0.0-alpha1', // afollestad - materialDialogs : '2.1.0', + materialDialogs : '2.7.0', rxkPrefs : '1.2.5', - vvalidator : '0.3.1', + vvalidator : '0.4.1', // Debugging timber : '4.7.1', @@ -47,12 +47,12 @@ ext.versions = [ // Unit testing junit : '4.12', - mockito : '2.25.0', + mockito : '2.27.0', mockitoKotlin : '2.1.0', - truth : '0.43', + truth : '0.44', // UI testing androidxTestRunner : '1.1.1', androidxTest : '1.1.0', - archTesting : '2.0.0' + archTesting : '2.0.1' ] From 97a0eda92c225e15818a19dc36e206c6c89b743e Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 18 Apr 2019 16:07:24 -0700 Subject: [PATCH 29/42] Dep and Gradle Plugin updates --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 68f0e24..27bfe48 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -7,7 +7,7 @@ ext.versions = [ publishVersionCode : 43, // Plugins - gradlePlugin : '3.3.2', + gradlePlugin : '3.4.0', spotlessPlugin : '3.22.0', versionPlugin : '0.21.0', googleServices : '4.2.0', @@ -37,7 +37,7 @@ ext.versions = [ rxBinding : '3.0.0-alpha1', // afollestad - materialDialogs : '2.7.0', + materialDialogs : '2.8.1', rxkPrefs : '1.2.5', vvalidator : '0.4.1', From 0770db5df51d023850386be139f87e0cbb667294 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 18 Apr 2019 16:12:06 -0700 Subject: [PATCH 30/42] Attempt to fix Travis.ci running UI tests --- .travis.yml | 20 ++++++++++++++------ app/src/main/res/values/strings.xml | 8 -------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 771dddf..b7dd08b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,6 @@ language: android jdk: oraclejdk8 -env: - matrix: - - ANDROID_TARGET=android-21 ANDROID_ABI=armeabi-v7a - android: components: - tools # to get the new `repository-11.xml` @@ -12,11 +8,23 @@ android: - platform-tools - build-tools-28.0.3 - android-28 + - sys-img-armeabi-v7a-android-21 licenses: - '.+' -before_install: - - yes | sdkmanager "platforms;android-28" +env: + global: + # install timeout in minutes (2 minutes by default) + - ADB_INSTALL_TIMEOUT=8 + - +# Emulator Management: Create, Start and Wait +before_script: + - echo no | android create avd --force -n test -t android-21 --abi armeabi-v7a + - emulator -avd test -no-skin -no-audio -no-window & + - android-wait-for-emulator + - adb shell input keyevent 82 & + - script: + - android list target - ./gradlew build connectedCheck diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2fe7796..3ac40a0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -85,14 +85,6 @@ exception to pass custom error messages to Nock Nock. - Donate - Nock Nock was created and is maintained by one person. Donations are much - appreciated and encourage continued support. - ]]> - Thank you very much! - Next - Please install a web browser app, such as Google Chrome. From 5fc1569099272ed3b8977d24613446d7e2b7ee79 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 18 Apr 2019 16:19:10 -0700 Subject: [PATCH 31/42] Remove donation options --- .travis.yml | 2 +- app/build.gradle | 4 ++++ .../nocknock/ui/main/MainActivity.kt | 21 ------------------- app/src/main/res/menu/menu_main.xml | 3 --- app/src/main/res/values/arrays.xml | 6 ------ 5 files changed, 5 insertions(+), 31 deletions(-) diff --git a/.travis.yml b/.travis.yml index b7dd08b..cf91e91 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,11 +20,11 @@ env: - # Emulator Management: Create, Start and Wait before_script: + - android list target - echo no | android create avd --force -n test -t android-21 --abi armeabi-v7a - emulator -avd test -no-skin -no-audio -no-window & - android-wait-for-emulator - adb shell input keyevent 82 & - script: - - android list target - ./gradlew build connectedCheck diff --git a/app/build.gradle b/app/build.gradle index 4b02af4..d6b315e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,6 +20,10 @@ android { sourceCompatibility 1.8 targetCompatibility 1.8 } + + packagingOptions { + exclude 'META-INF/atomicfu.kotlin_module' + } } dependencies { diff --git a/app/src/main/java/com/afollestad/nocknock/ui/main/MainActivity.kt b/app/src/main/java/com/afollestad/nocknock/ui/main/MainActivity.kt index 7b59bf1..aec76d8 100644 --- a/app/src/main/java/com/afollestad/nocknock/ui/main/MainActivity.kt +++ b/app/src/main/java/com/afollestad/nocknock/ui/main/MainActivity.kt @@ -24,7 +24,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager.HORIZONTAL import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.list.listItems -import com.afollestad.materialdialogs.list.listItemsSingleChoice import com.afollestad.nocknock.R import com.afollestad.nocknock.adapter.SiteAdapter import com.afollestad.nocknock.adapter.TagAdapter @@ -35,9 +34,6 @@ import com.afollestad.nocknock.notifications.NockNotificationManager import com.afollestad.nocknock.ui.DarkModeSwitchActivity import com.afollestad.nocknock.ui.NightMode.UNKNOWN import com.afollestad.nocknock.utilities.providers.IntentProvider -import com.afollestad.nocknock.utilities.ui.toast -import com.afollestad.nocknock.viewUrl -import com.afollestad.nocknock.viewUrlWithApp import com.afollestad.nocknock.viewcomponents.livedata.toViewVisibility import kotlinx.android.synthetic.main.activity_main.fab import kotlinx.android.synthetic.main.activity_main.list @@ -105,7 +101,6 @@ class MainActivity : DarkModeSwitchActivity() { when (item.itemId) { R.id.about -> AboutDialog.show(this@MainActivity) R.id.dark_mode -> toggleDarkMode() - R.id.support_me -> supportMe() } return@setOnMenuItemClickListener true } @@ -151,20 +146,4 @@ class MainActivity : DarkModeSwitchActivity() { viewSite(model) } } - - private fun supportMe() { - MaterialDialog(this).show { - title(R.string.support_me) - message(R.string.support_me_message, html = true, lineHeightMultiplier = 1.4f) - listItemsSingleChoice(R.array.donation_options) { _, index, _ -> - when (index) { - 0 -> viewUrl("https://paypal.me/AidanFollestad") - 1 -> viewUrlWithApp("https://cash.me/\$afollestad", pkg = "com.squareup.cash") - 2 -> viewUrlWithApp("https://venmo.com/afollestad", pkg = "com.venmo") - } - toast(R.string.thank_you) - } - positiveButton(R.string.next) - } - } } diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml index b3b1727..5f2f23f 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -7,7 +7,4 @@ android:id="@+id/dark_mode" android:checkable="true" android:title="@string/dark_mode"/> - diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index db28598..84ad226 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -13,10 +13,4 @@ JavaScript Evaluation - - via PayPal - via Cash App - via Venmo - - From a6670e2bea9f3fad4c90415bb1fb5bd9860f5bc6 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 18 Apr 2019 17:20:09 -0700 Subject: [PATCH 32/42] Fix Travis build --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index cf91e91..a955832 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,12 @@ jdk: oraclejdk8 android: components: - - tools # to get the new `repository-11.xml` - - tools # see https://github.com/travis-ci/travis-ci/issues/6040#issuecomment-219367943) + - tools - platform-tools - build-tools-28.0.3 + - android-24 - android-28 - - sys-img-armeabi-v7a-android-21 + - sys-img-arm64-v8a-android-24 licenses: - '.+' @@ -21,8 +21,8 @@ env: # Emulator Management: Create, Start and Wait before_script: - android list target - - echo no | android create avd --force -n test -t android-21 --abi armeabi-v7a - - emulator -avd test -no-skin -no-audio -no-window & + - echo no | android create avd --force -n test -t android-24 --abi default/arm64-v8a + - emulator -avd test -no-audio -no-window & - android-wait-for-emulator - adb shell input keyevent 82 & - From 82c1a17c68d5e630f31207d5c6bdfee3d066c82b Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 18 Apr 2019 17:36:49 -0700 Subject: [PATCH 33/42] Fix crash when mremoving headers, resolves #48 --- .travis.yml | 4 +-- .../nocknock/ui/DarkModeSwitchActivity.kt | 3 +-- .../headers/HeaderStackLayout.kt | 25 +++++++++++++------ 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index a955832..4e054ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ android: - build-tools-28.0.3 - android-24 - android-28 - - sys-img-arm64-v8a-android-24 + - sys-img-armeabi-v7a-android-24 licenses: - '.+' @@ -21,7 +21,7 @@ env: # Emulator Management: Create, Start and Wait before_script: - android list target - - echo no | android create avd --force -n test -t android-24 --abi default/arm64-v8a + - echo no | android create avd --force -n test -t android-24 --abi default/armeabi-v7a - emulator -avd test -no-audio -no-window & - android-wait-for-emulator - adb shell input keyevent 82 & diff --git a/app/src/main/java/com/afollestad/nocknock/ui/DarkModeSwitchActivity.kt b/app/src/main/java/com/afollestad/nocknock/ui/DarkModeSwitchActivity.kt index bf5422d..3220567 100644 --- a/app/src/main/java/com/afollestad/nocknock/ui/DarkModeSwitchActivity.kt +++ b/app/src/main/java/com/afollestad/nocknock/ui/DarkModeSwitchActivity.kt @@ -55,8 +55,7 @@ abstract class DarkModeSwitchActivity : AppCompatActivity() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { return UNKNOWN } - val currentNightMode = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK - return when (currentNightMode) { + return when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) { Configuration.UI_MODE_NIGHT_YES -> return ENABLED Configuration.UI_MODE_NIGHT_NO -> return DISABLED else -> UNKNOWN diff --git a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/headers/HeaderStackLayout.kt b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/headers/HeaderStackLayout.kt index 092d416..6abff33 100644 --- a/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/headers/HeaderStackLayout.kt +++ b/viewcomponents/src/main/java/com/afollestad/nocknock/viewcomponents/headers/HeaderStackLayout.kt @@ -56,9 +56,22 @@ class HeaderStackLayout( override fun onClick(v: View) { val index = v.tag as Int - list.removeViewAt(index) - headers.removeAt(index) - postLiveData() + check(index >= 0 || index < list.childCount) { + "Index $index is out of bounds in the header stack (size ${list.childCount})." + } + list.post { + list.removeViewAt(index) + headers.removeAt(index) + invalidateTags() + postLiveData() + } + } + + private fun invalidateTags() { + for (i in 0 until list.childCount) { + val entry = list.getChildAt(i) as HeaderItemLayout + entry.btnRemove.tag = i + } } private fun addEntry(forHeader: Header) { @@ -67,9 +80,7 @@ class HeaderStackLayout( val li = LayoutInflater.from(context) val entry = li.inflate(R.layout.header_stack_item, list, false) as HeaderItemLayout - list.addView(entry) - - entry.run { + list.addView(entry.apply { inputKey.setText(forHeader.key) inputKey.post { entry.inputKey.requestFocus() } attachHeader(forHeader, this@HeaderStackLayout) @@ -77,6 +88,6 @@ class HeaderStackLayout( btnRemove.tag = headers.size - 1 btnRemove.setOnClickListener(this@HeaderStackLayout) - } + }) } } From e2f7db22d1b23b6778e277ecda87e2692b5fc9b0 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 18 Apr 2019 17:48:27 -0700 Subject: [PATCH 34/42] Still trying to fix Travis --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4e054ee..15f5e8e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,9 +20,8 @@ env: - # Emulator Management: Create, Start and Wait before_script: - - android list target - echo no | android create avd --force -n test -t android-24 --abi default/armeabi-v7a - - emulator -avd test -no-audio -no-window & + - emulator -avd test -no-window & - android-wait-for-emulator - adb shell input keyevent 82 & - From 351f718df8b85ea0eba8e8591d3841859014a056 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 18 Apr 2019 17:57:20 -0700 Subject: [PATCH 35/42] 0.8.8 --- dependencies.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 27bfe48..f98d99e 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -3,8 +3,8 @@ ext.versions = [ minSdk : 21, compileSdk : 28, buildTools : '28.0.3', - publishVersion : '0.8.7', - publishVersionCode : 43, + publishVersion : '0.8.8', + publishVersionCode : 45, // Plugins gradlePlugin : '3.4.0', From a0fd44ae7ac4e2324a4f160618d14e4b6ba831ce Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 18 Apr 2019 18:06:27 -0700 Subject: [PATCH 36/42] Exclude META-INF/atomicfu.kotlin_module from common module --- common/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/common/build.gradle b/common/build.gradle index 76d7d02..5004349 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -12,6 +12,10 @@ android { versionName versions.publishVersion } + packagingOptions { + exclude 'META-INF/atomicfu.kotlin_module' + } + // For Mozilla Rhino lintOptions { abortOnError false From 35eda8f05718e5c39785000935701f834277d69d Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 18 Apr 2019 18:35:20 -0700 Subject: [PATCH 37/42] Exclude META-INF/atomicfu.kotlin_module from data module --- data/build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/build.gradle b/data/build.gradle index 5512756..e413d4c 100644 --- a/data/build.gradle +++ b/data/build.gradle @@ -14,6 +14,10 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } + + packagingOptions { + exclude 'META-INF/atomicfu.kotlin_module' + } } dependencies { From 10d7fe33f94eb50378b72f44cbca02ef5c908b80 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Thu, 18 Apr 2019 19:09:08 -0700 Subject: [PATCH 38/42] Fix a few test cases --- .../nocknock/data/AppDatabaseTest.kt | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/data/src/androidTest/java/com/afollestad/nocknock/data/AppDatabaseTest.kt b/data/src/androidTest/java/com/afollestad/nocknock/data/AppDatabaseTest.kt index db9edd7..e7d4400 100644 --- a/data/src/androidTest/java/com/afollestad/nocknock/data/AppDatabaseTest.kt +++ b/data/src/androidTest/java/com/afollestad/nocknock/data/AppDatabaseTest.kt @@ -431,9 +431,30 @@ class AppDatabaseTest() { val allSites = db.allSites() assertThat(allSites.size).isEqualTo(3) - assertThat(allSites[0]).isEqualTo(MOCK_MODEL_1) - assertThat(allSites[1]).isEqualTo(MOCK_MODEL_2) - assertThat(allSites[2]).isEqualTo(MOCK_MODEL_3) + assertThat(allSites[0]).isEqualTo( + MOCK_MODEL_1.copy( + headers = listOf( + MOCK_MODEL_1.headers.first().copy(id = 1), + MOCK_MODEL_1.headers.last().copy(id = 2) + ) + ) + ) + assertThat(allSites[1]).isEqualTo( + MOCK_MODEL_2.copy( + headers = listOf( + MOCK_MODEL_2.headers.first().copy(id = 3), + MOCK_MODEL_2.headers.last().copy(id = 4) + ) + ) + ) + assertThat(allSites[2]).isEqualTo( + MOCK_MODEL_3.copy( + headers = listOf( + MOCK_MODEL_3.headers.first().copy(id = 5), + MOCK_MODEL_3.headers.last().copy(id = 6) + ) + ) + ) } @Test fun extension_put_getSite() { @@ -470,10 +491,12 @@ class AppDatabaseTest() { ) val updatedHeaders = listOf( modelToUpdate.headers.first().copy( + id = 7, key = "One", value = "Hello" ), modelToUpdate.headers.last().copy( + id = 8, key = "Two", value = "Hey" ) From 550f8c59beb81abc6a15e0678f9bc2e3bf6fd5d5 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Fri, 19 Apr 2019 10:51:54 -0700 Subject: [PATCH 39/42] Adaptive-ish icon --- .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 +++++ .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 +++++ app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3311 -> 2410 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 3915 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4540 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2313 -> 1645 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 2396 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2826 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4526 -> 3468 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 5627 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 6624 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 7210 -> 5480 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 9227 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 10517 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 10082 -> 7908 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 13377 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 15198 bytes .../res/values/ic_launcher_background.xml | 4 ++++ ic_web.png | Bin 25559 -> 27656 bytes 19 files changed, 14 insertions(+) create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 app/src/main/res/values/ic_launcher_background.xml diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..80b730f --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..80b730f --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png index d1698c39a966152796c4bb4c1906b6ddd41b8ee4..a86dbabd64abf69ee77e2db2e1bc4391c24fb532 100644 GIT binary patch delta 2400 zcmaDa`ATSlay_S^r;B4q#jUqxru#yiDI&aGFS`}y_9i#xX-iEH{c^R4yKhK(UQ zo&U>qyUL?xl&U@g|ff;W;{#f`)rSq41-W$2w2}wU4bsY_P{q^_tD$1Sc z-8tiprAL2E&QGT(zuuJodW~+mo+Im;vP^EM_U#mL{N27dJS{6MAn9qN?LMC77e!;Q0BJXJ6X~~wRDeDgOYh2sJ66tjEYLxgA zDc(IH`xYc5t$oI7`B!?kUdO!-Hk-U}QLHh#{Sk5>zHhPTyR&{3_afPiZS_J6%2*v< zO0c&!+-2uF$6nMXo-&6$Mfrrmd4|Khf1Pb=os%VVk_%>T*cH@cROR|bK#WoS%M8~C z#ZOnrw=EOr_WI?)a#4DQdiuiaIqiCX4HgGGn6t=6%`02Wd&?wD&eVVPEhgP&8}ZO* zB5KE2RsA;~nsMkr#-#L$z;)>+r-JHvUR;_Zf5Av^rmTU;-XL4YEf*H8Iia3z&dOP| zP1q%4Phy$EYNZomkqvP^&(GyPdBUY+X|1TC>#pLV(=Ksf-MM3nvp6=jJ&%;?e!8MI z@PfaZgS{dp339ToDf=6Gl1HJp11H z=>kuU18R0(oHwm_UA$9Mi{8@1vf|wpwQz@qKZ+K53N#H`gnpqM4d=IA`6} zaaUOuW7$$>#P`~pt>XLB;DZ0($`flHTZ0PNz8wD`$l9CEGEpXz!>AyV+hNur&mPYI zWu=|X_wU(pf3GhRsw>;epR-U>ZDE9El4ILSi9Mx@1?_fJ@=Qyft{`!#vF;9k-va)+ zy@gUWg7xAWwT7KsLFwF!)_GkfA3C25YJMDB{NbE;df~M0Mm}bJ9rgNe zI%lOH=>IlaLJg92F=G>>r|L5Ve#~+?um2bKxp7L7lB$66OLiBDGXn4qlb=ycOTJ2}{Z zvwq*#vs-5H%x9bXjLGC=iI2*~mefNx^(1Zjzud6#33xw2eBR;b=gasG{Iug;x8d-I zb6=My=w9TWbDy*RNZz;l@AC4gMJ4wNfBY;Gc3JEuV$!VrGRLv@s@RoA_oxZV9E%K} zoxS?`!^6Ano1gr7{4Lz!u@tkaT(0gkXq$x&I`^_GFKs=7vS&aC>#11cv3 z`3~gg)$so-eg65wd+UB9OXEaU?g>Wi^66&$r&`5Y&n=Mt_v=)6V)90LA7MtB;$;Wy zUbe-@{%5=sT`9zNH+YR*wkT&6_u9ZKpUbg*yt_^2>^;eBQpKg6W_@sDq)70|{yG2-M zUJ4MMH*cm!0FO@W+T>>jmW?SNi(FQxMLl1!M{&l1cP=+Aj1F#OjGeIf!1p|F-b*U( zN=@hCu7C2?k zsY$BeHd$FuGh~NGO3(2hXBORG%EDQ+MA2imGDm;fwh42m9_AJ@p54guQdMmQFKeou zl<6k_f7>Q)T03LXlN>RZ%`=X$+}y-kxu|k!2J_A&q3Eu_=N&hVih}}l)dC&cOk^Ww zmrBWITCwmXy;-9oa9M4E_=8OuN56)x)^qmOi&3nlBIV-9OFwnUWJ-M+}~KR>@!xMy0&M6kZe%5a~dsJ_eR_gCb zyAG|9Xjy%MrNXhu;%CxtwIhpOR7OpB@n6=}BA78FT_1u~-Plfz@vS_DHl*@&cd0W*(tYdqa4A~zqnBSpv zS=2dO>9*MPAMY$3e=hs!HSvf^{y+O2;m(m4_ew2%61Da|-_oMc369H7{-{}dKR{i& zX#G^(j03MGaZ9h>a^73JI_!q-%q8F zZy?s?nfHBPyP?^J2=Bj(8sELk6Z&#uV}AYfEtf1m&g1R&)~j3lWL0cY!uCb}PEY52 z|GU2a@sDDW$1{!7`QB+Sm$fW<^7u!AMCG5H?Dflo(|2D@F5FXhGH3tgiD z%lIGtok%adDN!{x6DmXU36r57ZVg9RiFV9hjjR8KpKh`Sz&TfIWTrU1&U)DEA W`TxqVZy6XE7(8A5T-G@yGywpRQ)xB; literal 3311 zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84mJh`hS0a0-5D4dSkfJR9T^xl_H+M9WMyDr zU@Q)DcVbv~PUa;81A{`cN02WALzNl>LqiJ#!!HH~hK3gm45bDP46hOx7_4S6Fo+k- z*%fHRz`($k|H*Yfq{Xuz$3C4WFHv2oy@jlVBmh@>EaktaqI1z-~BS- zQ;*v}53^rZomM3`@1t^^?h#JDW76s^3Wp9K(lOLoUHfO3_FFxdru$*H;>-Rw{n=pu z_Pqy3N5qj}g%$;cr;ZBSm@O0)H*R8Kx4tp2{rSbuZ|1FARsF5~Re5-5_}1z*y(Z}< zv))zv->p9PeO~psozJK7R&Q~Kp!Z>uVjtC-Pq?@7lKj6L>PE}uYu|*ZO}Aei#;@67 zb}UyqZfmig>&t}8=h$!U&wB1)J85;<_L2=kMqEd}E^JsKICFE}Tk-sTpI)2m#qWBs zl|&pzE`{%Pi!`q;mJPsdljY<<2e(IRD0!|v~2oa>`+7S3O@^Ic2Znw;XT zw|N(EI=CmFw=!dVbz#Z&{po8o=H*FWT%oUPP%Ci#b6?fYHBo!m_p6>q^^4Bj;K;S~ zWb?Y`b91)OF?jtl#MI^HhGo0^J>xB7&s)!w)|KTlZj)+Ia9L~Uja^$R6Q@r55!<);@Y+>cN|SE=|8gcyK0M>+Y`5mGwcE_EZMgPL zXV>#8+jnYQ3+8ROJK=-{-{Pg7MmKZXo8QLH`S9Xe(zJQsR{$Mb zSwuT$OVGqkZVl7K=9nz;ocH>$5O;vaBPsi5@0PKa+jF(GRhpcVG2Jy;B|3Y$@%&hc zJ@3W5QGKU5wZIbnVx%;&R*M1`XJ$$cW3j%yQq z+=IlIr&I*pl;4rDa54+i!Lp^l*kq#$)tD4=Pj@*_;ATATG(ohBZ4>W?t&^CqZ^%!K zubV8K%>Cy4dZtq`sk6ev`-3*~btyEQcyP|vCa@=q=VY@^(}JGVtS7S5S4~emefC=G zWrtlY4^+O}PB5I-e{Rpo$D74x7;%T#Its>pk$)yyEpgxKjM%mhS2u)de_^!|bx;)T z2-w6Cyi@nwyZX7o$@zgL+ira8-m|f;>AASwfm42hhEc~of*OSHr@L6ze=w@I{apMn zV%|gR?&muLEgOyod{bMo>hQ#kM)5zo=Wp6!eDwPNFX0ulUak*FYLI&1QBnLsy5aNr z#`Fug;ON;-XpP%3O ztWWvI108mmbWDrcupx9@(<9=(5e$MhB@*Y`GR+v=oLG}6=Ko;^A7{y^2&;FS$h zA8h3`{`76$ynewo_uQJYmA%Zt$Io24cKz2oiTTHu>1_^emOnRlaZ>k`qN~sR>}+gUdeZn81>RK0Jf!Qr;q z=|ySwts4s&_C)o5dRu98KKqln_v9XbU-qyh-R$k+E5f$TKK#tRYf2iw!Nk=CHBYSS zZ&;jrbk5GM_;ms9r7cT{0oQQf}v+&V_5%9Tc0 z*P>$-{gxb%+WN^i%*?Hz$2qY?#?UD>yZLFf`G&05hc&IIaxE5~EOGqc>bDz8UbAhz z<+nL!;@PJfQ`AmA&F=AN-DKUE&-;{1W`1q6{@fdG0cmHpT3Mu56ue?PetcSG-9N@{ zxrRa=7TsMMub*ap><>7GJe^E#o4~^ zE_SY5aBhj0+Vu4M3zb8(qjkBpL{2^{zOu&q>UpD?w~uuc75+3?WcR=1Po~I^V_QGR zMAQl}+nD_|daoPzJe>Qxp#McZg^!v0=CY(-*8lYD7iVAJombnoK3lFW{eANMo&8Q~ z&5yS%JC#y=M#fHTXWKD}WqdMRkrJtwwTp6p3%r-!f9~KRsqNd;cW(G4Fi$Gv;nGi; zYoz%4*L~c#G5b&AUj^wr#va~98D7F(PnI->b%sU^hCD?lBrBxI@P2@^z-fv$uF({8co>%;I`i>C0=A(&9@sH*E zVwNPB{kVEb(#DioJ|#H)(prhdYpQ~4-p<|s_{~1=IeM|FCc%l9r5|p+`u)S1L+p`X z)e4Q8Bwl(-TyDI)ZBbHX@n;tQ^YtzJcRptl{vKXY_AxOphn?@=i5FbY)AWn;|8d#x z`Y5_>nqJpQ?|wd-=snM~eS)CI@5_G@-WArF?RWHB74lbScAVgm2PrJcJW9*- zB5N#OvimKVpHNs)^-)JUukkax-p8Yl^8-^w8U(jR+&lN_Z1(dXPd_O~%t^@IwcOuB zvnJp~Z%c!rf?xZ9avV^O&E z*@H4SL$`>J={vTVHBZZ(?C>xpNxW@%;KF=`LG$EN2Oa;S)txNM`yY#O>bScKWSZYSBEiFPL61TBYs`|XDjivK zbKWkSomUvdc*SPt_ZXS1`PuKje4V%C!4g^XXPwsUD`Bx|2 z*I~+eUra6<>712zxt6l$Z_A`awXR#=ZYyQinw{2`IL=wWs$Z?}w&os%1uKtrZq~TE z;9N>|e2fIkf{x5Jso8t)T+#R#>UUy!MS{|g*}9sS+WI!W3tF^dR?VVwSKm#SE&c9s zBqCE}@8%uy(Sds=?|xUu8ULirW9QmO$Gj#AxGfTo4)o!!TBKv4YEaHN=b26?V^MZ! zc<5b~A1d`b6E~c5JmBfQDyq1=ENjdDo#D$j80de#en0Npom*G)91qt`Vi3+Y-Ob<^ z_4?zTTUT4{arb2EEPf0nmy{hfLL=e@6@^TYX3*Vg%*W3HS z_Wt*<#(DLd1)rwLEJ%@ge&FJ7ISb?B^Aq_~iV!zKV^$PQ> z_J>mzxb+n7`8C^laN!RkNy9xtSyayS0-%QegC`7@}QM- zHiyZ-ysA4(s_&M>=i5#TKdgD2VpZ$L;9Xgo`Ej-V-*3U&QyX5-)sR}nI#(znHu|=I z-IMz+XC4Nq8TyvbKa;WL=lggan@xc?D^V_0v!O4YvTKM$SM?YTL9x~H6<>jnB%S3#e4qS4pOf9|f zi$}VIxrfo1<@t^)`5ycpTse&1EHl4d5IUL2tilo&x#Iuc=>PZKAAg8cwTS0EJMnEB z6Z5{)rXpTHf-cLwy(stg;_l{u{Chud_gYl@c{T$BgKCLuL`h0wNvc(HQEFmIDua=M zp_#6Mg|2~7h>?MnfvJ_LiMD}}m4U(Zj0<~EH00)|WTsW(*6_?Ug8>9QUHx3vIVCg! E0G=>Nt^fc4 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb43a7b742fc04c526ef0c942061fc0c9cff21db GIT binary patch literal 3915 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 RiGhKE!PC{xWt~$(698z-M8^OC literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..45671986b40e92a6303d9ef77382ef5f1e325b7b GIT binary patch literal 4540 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 G2~7Z+F&!`f delta 2302 zcmaFM(YQVtoDuIE)Y6b&?c)^@qfi?^b3~Wi>?k)`fL2$v|<&zm07&r?& zB8wRq7(Bq(?PRtc0|Wa%PZ!6KjC*e*ynABYMeA+1-+TS?e98I$_QL<$dYtB1NPM2y z<8YAexS&hdQMJV8Jq`*Ryv!Ry(_PE=hrhqPKVjp+@?}^5u6h+VxBC6g?W^Pp{NJ7Yzdc~b z!`bI+`DbUZu9uzpZeC(T(3v-1kN!1_%KC3mS8={=)%{Zk)1A-Gn0esL(V)6w&Fl67 zb{`Mc96#^CnJ=w|UMl++PqA8My4=TMDyt>Osf=Wa^D?ZjtQE2xu87?iQ4+~L z{Y!eu@5Lwg_TTyQar6BSsSi`v*UEBVPq$M0Ui;|zx}f`)qNFGPs^_lyaPv!4?E+Kl zSIzyeX3yPfr^vy1`rpw%`|nk!RUDu9NxS}sEW?3yyl99zw{G26ud=8T0wZTW51OR zf5mPqoipDpez6=2xgHQyr97qn+T7Nr$)YEF+Rqyw*d!d_#pyOR{EWb~-ggHDBeuyh zJ!9^>aHg84%FOS&iJe}C*RCD4*^FME>zy?5peGfT)9OHIBy)n(n zN#luCmqOZ;yCSEe7+kJ~-s)@!Jk2y)y#m z!vV=JQQ0R>^Th3{!*>6j4jEG5exscmK210WOAu75RKoQ$Jq%v-rXWM;F6Dg&$WQzPi)WGQr}? zf3bV9w_C&O!|j?UZF6L)$$Y~jcXHnGlQ)$$yciv}IV%3>%z4wBpjHwYePi~_bxq=- z$)chp!D&}DUJHg8{Zz*Sa~Ml+Pvq@ zvuCnohrTrDIDRm8m6iPO)+SSiwj}QVF?TzecW%Bh-@04)dS8O~(}J4o+9z(Y8n6dj zuDc{@>5!(;lXgt@W+%Uyebd8*Pj6W=GbCHtw>~-1d_pBCA+1CuSmLhjQ{RBaq3&U^-TAdh-0q%veY5>p`6KJs*)gUa<4u=2u6D0wN@~tY5r*CcE{6rR7Kci0 zJRi+)L8qYV=jIDh4)9u^ zmS2C*&LDI9BOl+BWraoG3{KtZd*;A1mx=91q%?~I!>3i;^)WRv%ky)cHXo~(-7YL( zrgNIfL&8hug6YbqpQjZr-N3&5*}jg$&F>TLpX+95FjeoJyt%!wvf5ndU;wXI2~VrV zmyfq4c!U@x_wISe?0nd3!KQ~34EEfUvDwqX@L$j8(W|eVPu5r`q&-O$(%xn6E#)RYnN{29eKg?KMUfu14Dz%_I@^Bzh&m05m1z-wz(gZ)NN3C-8?D;~W#aA(It(Ya-MuJah9!e8*` z&9l(GKP!silG%@d(2qP5@+4D_YZ`7A4&NuG8vkaN{Grchd!Ht)d?9lB>7wh;LKm(U zKmYhsb^5gK*0<(a)4e~hXHDPIs#cJi{?=>y|`RM$!^)XiL z3&Nz7*#sI&jOI$dmX^Ca^M%2^ho+yFU9-A6bMN~4lt1k%F8hBz)8+Bh-dk3k`SADA zL*HZsIr&#C6tI|6FW@-M``oWfk8)PN&|%P+akngm^?;^j>&>IDjk!7YnrA6geR}wp zKh#F}z3=}R-f+#*ynm;be!o3)|Ep3-zRWv`eXE=AKKmT@q}boCb?edDtOA8^BLr^j z?%mAiSfDjo)28ap>elP=c2{2sl`ft7Imn^U{&%d--8tSRU%&Jj7B8xQw(x26cDV~G zaV!@DKK!k_VO!O@#m>&gs%qsnJHef^w_g`KR_?!R|Id@3b02QJEya6aqEw&u`^~XG ztCgglzuK#BZZIR^?BCwF=CIX~@`8VFP244xc<>B2Yq;%Ok271km*+B1+L`yn+}yac z?~~{^Q$|nc{Wb;`8g* zsb9amJ%01KZB={nTN*pIeUjdOe($zTTk0BaHDB4r7`l-`W%d1XXORXWrrn=ycdGvv z{#nk?Bf_+N_SNN285kH;OI#yLQW8s2t&)pU6H8JVj0_CTbPX(Y4U9sJ46F=HtqhH{ o4UDV|3<^HIu0hd|o1c=IR*72!zopr00sXq8UO$Q diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..666c904280e844a1763b695a0b7730d744244abc GIT binary patch literal 2396 zcmeAS@N?(olHy`uVBq!ia0y~yV8{Vs4mJh`hW@nhvkVNJ%APKcAr-gY&d$yWelB_Z z^2I*UTTWUT-U|ghqnMH@3bfsdj9OrTo$gTtmIc_ zsR|sgtv)8o&-mf6Jk~Bm_O(gotyQ%W!At9AYzyLDU;Ay}`tz1{+s=FD9KUIG?(_6I zt1`WPbLP+gZu7pn@A4%B2_ClQg9*e?g--`i`BSS``^O<>ozcOFsB8PU5Xcy*JkB)^`uS?;{!&=s$M$FBrdlyzm4aEDx4 zd$~6H_8rLpX&K2cwi?SeeOdP{r?&e2-c@eqAy&5}MQy&Bx$V?-nYniA!j0QnHnapp z&yrmFOh9#+nxLNBM#CeT&A~3pi#_C*1-uu~xX^jwmU2L5ZjVv)>AgjJwWBqsev5F< ze(oC=(z53KMuRx9{#$SMc-}iLE?*TbDJePov_7zLJdpnEM ze>vOBq@_O1QD4*~s(r$1$*zCmhdxQ?9DJ+4Z^z?Ac`^A)JLAu-T%3v5{&{ZT_2Inm zJ4xprC!?|deT&0K65lNSp=?l5ag61QZDNV-Vy0Vpg0ad>ymOrwT)LUul6!k^^>m|_ zo41=Dty;7_HaUIa$@)IWeD}vPu?Z$!k~7mSTyC^KSK7ea$;lB>tEjW@ra^P!nPy|A zWsR9ZgZ+gCR9sys8Ci6wBC?SCb@&d0q8hHQ{!qn4?n#?eR(m^LJ9UUj zQ`jv?C;T80M9h!#9@C`eIz-m6Egk+sGb%q=-4H|D*VEy2M3k|Q%*;+=qUYvCply)(B? zxwxDz>O1FrIf6mPg<ubLP!{@?M<=8jE0&lkD<4GYU<+|=)WIC&{- zNAb&4gKvF}8}lbQwsxjyde69ZN#@CQX3eC;_47-QpJ)?f2rKqYxm*j`2#0h*e9EsiB3!X&{H6! zKEptii<>)mvQ}}y@#Wj~r+S`RWV2%)-};rOAI{h%`Uu1d-!qEJ8kO~RpdbAk`w7b`bPbW?gRtHe3&+Tpp~E@9^lqB-`t*X_56 zSJKv5f3NG%iw!qS%{cz=`d8AUbLzaFOseyond=@*mX)tQ6ScE<`Hy3_A8vl#fB3_W z*`CH<`wl&w8RU3v!hT-6-P`1Twa>m8;Msn3#jBuc8-#*`18U^D^M1bTHxm(0>vf6R zrO@?h_xrc3vyXe1&6^)OwfD`Bl$5|TOG5vjEiZa-cy;xH>LbimpJwnVt?$0`|HG-g zA77>86+fLQylCuKXWn<{$nr1BEf-fw&S|}D$NxuRLECHYp9XKQH!rO22%Ub?`e0vR zh?CJKr$cE6Odm9V*Wb^=pO@1Zzps+%Ufp7*I@fLd)3zP>eg7;=^?Gxao)ecQFH?&* zQ4xyt62Eq&Y|Djtm*@H|i8#?>T9S0>{I(K}CE9}5X1wZ(7mKcw;#hlN_OCw$d7Ieo z?VQ29fBzo#I>&9#kF9pRZ>tm{Zrc_Za!TwOSC{|O;~diS9+&;&$<|w;vQ2hQ@2WKp zk2d}I>a^{N$zRS-&P|ov3-qb*kk8M%WfW-#g(%C z_j2WHLMsg>>WCcUo;+=eRpg~ZOFBfvLSs(}m3h7A>C$&xeEY^a|F}t0R&1TrddMR2 z(dxpbtw;5><|T)1+N8mz&($sT>`Bzu1Fu|yB(FA zZ{3sY)}0oV9nGV9?OKG+M3LY#x&>VVs@$z7W8HLHe_YDCd3ufNzFMX7o26GePrl&X zBy&nI>chpck@30<-mCgDF1&xFKJRrO&((=cXCHk$)mH8wlJ(w5tKya9@uwQk zGk-Mvv2`hqnZ_0+DKGHOEvVc)T$ugUt@8a7!#C|HJ+7yfE&V-CMDW+$2hTaGIe&BN zs~^;^-n9Q(nZ|yR3chF44;-|~a$<%_&U+jEU?a(vRB;oC^nsWa>PjF=kHz20PA;H78Ip!a;*xi~l)+HRA3=9km Mp00i_>zopr0Mx{JaR2}S literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..3baff412aa42c09974d5b29905d71fa91591c95b GIT binary patch literal 2826 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 N;OXk;vd$@?2>_S~R&4+P literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png index a4f8356e1a5641c7d2f81b0a552643212c1cd374..27f30d226e10192ff80b77475018a0a22a0f388b 100644 GIT binary patch literal 3468 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 A_5c6? literal 4526 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 U9@@`BJwTRwy85}Sb4q9e0K%?@`~Uy| literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..1d29a541d709f7fdb6acf29a91ce15cae5c1028c GIT binary patch literal 6624 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 R85kHCJYD@<);T3K0RVm#$!-7u literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 49dd22651749d153b05d6ee17f639d1e9c757f15..60a8d1a62d2359c57246587d77cee585b8c64335 100644 GIT binary patch literal 5480 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 XTf+~Dng19V7#KWV{an^LB{Ts53OUwX diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..7cf19eb10cdaf3b1809fa4ba6a60f47388bad99d GIT binary patch literal 9227 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index bd57c86dd49e3d70c458a2f5022a47d0b16146c3..ac61bd38483c3d57c007d1490550f6d914db81b4 100644 GIT binary patch literal 7908 zcmeAS@N?(olHy`uVBq!ia0y~yU^oE69Bd2>3_*8t*clk)R(rZQhE&{oJD0sA=IYGj zxsSD)dpXTm4n49kQ&i+UDv-l-LqvS1N7&}8rdo^FX-a*)nBkVYByjuFK1Sw+w>C9y z*_^o9)6dL%)9yEElXE-{&6{&rD2R_UXVY#*^L>B!{l3?;Y>%Yxb?KM8pa1DkiQbm} z>~G!oy6^jb-@yVPs}`PStz~n!P(M*mQlq z&bzqZ_KrbOlFaAkV;6<kvWCb@MkZE4=0_+!V}*Joq17WBwGFVL7CdtX`n-I^I}eI;sh zSmads`7-nJU)bzB*#EJYsa;q>-n_5llgFQ^`{fS|7MWb1t!wIE@zV8N>Fb~Nc~h!t z>~_ova9Vuu_}6Cl1*gn1)R(bDXU&s1z1p^zxA}3jjhCF=j5!}v8+P3b)G*nqdRpjA zc=p412=!amTli=Rb9XCr{%?& z!ZOE=G8i^xOI_;N`03Lp)>Xm@-6{t}zc#z~7rZ>&`AVZfCs1-qeol3p#O+19j69?! zWqjIwz@+3&d(r#zOa+V78VVm6WcbM1yB(XvlARSLSoH1RPSa(xKeFyu)=%8XFy{pe zs{yY(vv2Y7e0k5azic*ci}Otl2n)OB^y;totTpB4J#zm$SRc65nsV%)Hv6so+f%wV z9TDDsesN2r7$?1c_2Q_Gj>(q1Dc`?29R9HJbj<^cK+a7rKAE?x_0`g!mSNI8 zSN+7Y-Dju9pLtXh`?=PFDJEk|yotPxp9!mm@%NY-72S09joS>hvpa9GL`(|K-8G-} z!I7YbwJU#@31zPma;P)(ycv3oJ%Yhchqb~)HCue+wz~84RJL*$_=_dH+{g8|S%*P= znd*gkXYL-ErE|bWtl=<|&vu4S-HD7AhT;z%-j%HG*s7m_+luXikXZ_m-T&(PpoU&F?937)&oj_&$K zFJ`Vga52#8uJMD(R{INCeAWi#oLU*!bv6E%vp4%vf5WTiE}Xwu{YsLt_CI5x&Wjl{ zl2jSF4LJ7;+GjK;%kX>)ym0%MUf2e&YcF}9p=s5>r1Q$pWj>bGu35E{qF$-1PLVpg z|n$>N@7S3%}kaYGiNmU8?<~bZc zb%e>qpCKyq!dKY_uHydtn~v-MDb%W87R*rp;dpd|Yy_X^tXm7u)j7x*iz#?Letn4!R4}+XVzJ!j!(x6IaaOtJ0Ui=i{oF# zbo+@u4T}{U?0+Py9@u81`{u~?6}j(O_a@s^rCwMg#-JXuYhQCowoTwa7S=kGhvA`r z*Vi$=xPQUqrprk!zX=-|CUOU)%QruI<`@2UzM$%lbf=$-%^0^mJ}){$C*ZoZ+FG`a z3={ntR2faqniVE#O8oGgwB}S*xRIvly@mCsjbHxwe(AL6qEdd($20d%F*?6w+RFf* z_g6I4mL9QI=?}^h*&MxCWXcKuvY@UhL9LH8)Fq#Cgf;y6Rkq@-Z0|jniZbp3mpgLN zms47MR z4zoWKxebISG1NUwXA}x)aLaah(JY#G!+|>M}>|pbtf6E_E z*M^Fz_BsuxSU<$w`XZ(f@!{{m`5Aldxed5kK5Sq2Ue`h6gL=?=`SYLJSp&Kmp0+hS zsOAIW)`NcU_wvq+cOIrQKGJD;bnh<%lZ$ZO*02A9 zr`dB9uDoij>e#{>FqwgI0l$ia!iVL;|02HsV<~W5&dg(L8*u+JubWS3y8RS|3qfpx zd76z6z`?ZP;QX*3%Hj)z7QUCwYh7;_$zfleX}zcR8)L=yJ8VDB?)3f8eYyWYwtuQ~ z@_ODbU1mMTDK0a-81jEaGMI7%M6t8>ZkzDnd!yvTFXuu&tX}wCe=~1m=?2-j`aJzV z?^n-nKD|DMd;0k}>r62cH@T>G|rk%G+)fe3fH%VT-kcvWmokiwO){!rG?`=r|;C zJSaVzr@*LoP`-KAJ;4mg7tF_Ju=dGiwlud#9k9B>`Rg8IOWeMyo_)JcFSvAX{sViP zyoT>_JGu4d?~Xc9_wb8Q#s8n8A6_rdYnpGjk?)>Wsqvn=KV>WO%$)^e4c)@0T%4LF z#$Lj^pMnBqrvd$~5Jr$omTdYZ&}~tQPn;Pf)t%|4*AAm#>>0T$-Ph z|Fd_il6>9cvL9D(&MkN~L$2g5b3k9i)bdjkABM)iG-hGvzj8P}{^)mujVyX|BYE=e z|7unwX|VQ)E#5KDYX3@huGzaCE??4&Wzy8^S7H3Muy}#wJ} z7unA5F;Vq{m;+~>m_sX5#r1D2|HI`jADq9xjz6aEYtB-Y7pFI^V`1m^eL9h7b z1t;$@N45C4I5q`5>~CdAb7%kaU3>m?FPWDA@B8x(#O)L1ihdh#<(B$BE9d=XasR!A zO1^AAuv@sCyHIa_B*XriUz-E6odeHA$nEr;urxcBQOJ{_UikKNxz(-x`^vgQ)HDvh zpBEl>X!i2$O&gcH$NaI=Jm?Ye;5bv=tPlG>-Z5(_-ze}Py4~DyW#p@;cMnc~u>JIh z+pP@O{;B==d(%4h!~Z`g&pWJL%38lHUP^Y3&;*83orYJe1@{)K-|uJGyV&f<=hg8O z9>$xMo{MWuJ?K^O_GE3qt%m~T)dijn7rKrJ{7Yad;4we+bMtDJKmUJT$y%``;?IHi zW#8G~{Ir(s{jj^!`st)h#y>32IjX!DtF(VkKl@3BQMEw)fczgFhaT1s^FI8lKGD30 z;l}U(4{q*_xECWV^5b1){Ufm#FS3QV>j(-(tW@EOZOS;jek<>xZ2u)4_x=lU6=W!| zFPz$-pZB`8P0u*v!)uj4m(~XD68LxD??FnX66gPWPCvdM&u2__xBa&_P9vvK+)awL zg~1AxZGY5m@>F0Hs7t=jP*ac>d*VZ|-n`vx^CV9<)$S5I;U-YT^OhrGzK!EI*10Yx zO-mi}{-zZ5h)vwXHrs-GwFZMz?2S9Rb$YjN@ZDrPFJcm`Y4%2F!M59c`>Vc{UHtw3 zY3tK~dwI?osz3Z?wOY&1kGCB>rbZ=PT$MX{IPlVU8nuiqn3#)ca-;Ih*xKz143^i=qWmU1vi+n;*_UfA8t4pDUk#Z;KCP zIQ@j<0Mm*XhFxnD>YA^9KBL=I`NKgr#$vY;&yS^lEM>%|<|BcXxK|?}}N~XFnY5)^253KR@QZ(1J@j zjqhdlvg^$`*7@;BQpNu}Yd;(^a(zrV%%(LO*M5{SE>o_E93e`kE|J`UR$CTrFx~=J$U!{}H zPOT-53*@F%7pnfyyj|?Qaf;+8L501Guwq{^>J zH;8kKt_0(!h=v)Q3U@uWm7UVyyl^eO@&D`yNv0o@KLq=Izt4Mn- zm~yFQNAV43hF^Bu?=kIu@$SqG>8kcP`Kv#@CdWyMUJ76;G*8=gbw~Aw?=Q}CxGiV+ zl_$OD@6`Q*On?3z_3!3f|NE5x(g_dbc2rbNWSC#|&wPFab7|V-hBz;MuiL!$?JMnL z>}=)jY6>~Gl)Z|boc3Hs!PtXQL#Kg@Rl_~te$}&U6Amu_^Ysgt#3u1X{@coG`&HB0 z8$w?l-OIwU_h^xUKWy&4;p<{U_Hxe?L)u&)yGbD(twngm8Sg^^kXR{r$B(r`F7kYFN87Ri{CU z<%Dsh==WD4H)KBatG{pcPM^-oYWLJ%KZbpq-&&367^W?!nQo}P{;}iGd!Yo5R|SWD zoijG)U_3WJx^?o6tm`ojIn4$49?7`t_g|I!S-pBM<2~!Weh2>BpO5Dhi=O&ArXgD- zf$@rN!*^!oKb#JGw{E=5^#9L~sz4(j*8lQ?|CnokAN|VOde(Ll!!x^$=i-c@;4==OZ_j1<#y=42y z<<`;ZVh7BRzjywzd+Ef5sX+|4OlKLkGO*Zl3wSg7$TG@Vi$pYVZRgaQs%w?a?jv)D zvA*J;o9hRAn_|;Fg`c_;HcwUhV^+wtO2C_~|K9vl^3xeMHrjtk?Yk5jyT#xA_C4nH zvOE2In6^Cn{Cs+TW4Qk_C+Bi$raP~1{eC=U!L_v3<$Ti*zE{s{_bxG$sQy2HPK@?+ zkG=DlPTXF$d=~QthAgoImRu*&qfZOW*;Hn2a{JZ8Cka+H(hq-LOfEmb-?zTKbEEr$ z-K!{3FNYv6w+OblU8-9}c}Rt9ZZDzr)tUp`k#N?{KV-+d+qk_|9x_U!|4S&4X;>U1l*gTHh=5YUEU7o-zo{daG1=) zvAa5hn{ldbNcQdr+x@QoJ}y^xJ=fQRsoR9>!X#DB+gYpI*7x7%&$q8-{`0hT^@GLJ z#U7v7z;W*Jix2hsdad_sQ&nrepO|~$?n=j(Yvn$OZ@E!hRlh6e(tL(@A2u^wR%&>k z>|Xqr^MTsICmseW_6N@WEUh3z<>9wUhL}kTl0|Lo1s4_!(ocH6I1d0OE`kfPuOxGCQfV@Fo-Fu)zq(<)*^j%b3%YNb`f=X+9lN;kx6q0e z@8@Q2t!{d6_4zfY{oma>2Y7@JY}I-)F;P=b(rp<-yzGbFd4(_b%ppSJ%86%UU{7i<+Jo`>PT%NLl!PvK9;szt>hu0$_8YGntc*GnCxBug; zcI{E$9Go};UJCCznqaeV{>u-W8CD58NLIXGGVP_p;!`3)m$VOi z&+@1Zxaqx;L+PnVa)76RL7^_?4(mb}s6Fe*vk zq44Pa$+rh>&Y8^MzH^w9djbQK3sbGd2X@|lTo2M2(-tsXWQfzx zoL@G+`s&Rx-Q|6ju;>ahR#T?XbP3gY=b0hRKYJlnw;0*xcWl-r}m|u;jpT;Xf`d_ca~t z%EC%@97%Vxz?(+O7lZ)1Y4~7@M_d74W%DD5Fn8<>d zyBFFy>ukK{MI6#^VtVpo*1|=L<-gRjAKjSDs8s(sLBfLNYOHfWk8`$FAJgs6r>?Nq z${Y+={?nf#-hKQ=)~q!FcP%;Cjw=?viD<|;!(3qG`njQ~TbAq9*$Hj(U$)%|3e5M@ z{vg<7FZ`h1WI2o6&E_F%g^=g-H_;>6|u9ty6eQXzpfJ&tvvL9`>p3&e=M=sv&2VGs&%tg?}Xsn z9mf~(_Is*_JleRBmHXoF%?yDe4sxtLKMr1Ek7+eci;U*akXq~1V)Lf9=fZJ#haYV&Zm5!tXZb;i02ky%WQRfpHCsxmy-YjUuMZ>Gi1HSeUv z6fR}YICoyb@AwSXfYc{fSKgWzc%z-^PCG-pFlXJ$6fQLthN(3w@plyF+&e#$H6UA! z)gbZbWHC1U&W16;( zLld{c^>16IhWmVCa?v?yb?oRWkFeC*GY8AnnAPu?e7x4Z^!Unn^}XWPV;Wf#7@4kp z*>a>S;PqQ}hje-2-%(6U#i}2j>Z`jEpWD=asfa1fJIXBQrgUP^_wI|!HZAu5b3b^m z-Q3!cJ^ar9cWkk>6jV)Md?XxrDIrqvo3vz9Q~y5JPbIz+f^RR7u*#kto7|pHITK2b-$2}T*2Ze-ALSg`v1iziWHOw#A{&St#5({t3%Z`c2oH-rc<9@rn(4IsHySr(YcrEzx1%e(>L>VGqx)_1glg9=J7%P5P|NbN8@@+f6~2 z7p8Bt)-Soq!Hcf$)AhPyF3ueR$XGNxTfv-p`*z3ay8y!Y-GF4XD? zTYiyS@nzxMg^T`lUgOPUH;VBq6Ez*G>y02)o-z#t>0z{DuUX=@F{cL`;$L@SNUZ&p$EZ1%U5$TK0CYf?Y34GhP0&z3t#YxH3*+wt9j#h{4(y! zP1(}*eLZ(IBBFPfO-%3?WjZs{`2Vb}+0!R7gwAdDH$Qdl6XO#XZ-!kVrlG-KwG7oZ zo5hDRt%=;6X1RAqNv<#B+tteh5117FNw({l!|~a$bVW(*;b*olOOM=mb#?Xnu*nR? zN4s~vv(jo@cXZ9VEnog}$5tdt*_I`S*&J*U-aU8c;^X=krsmANb?d*wHalgB=$)Uu zA{%yQ2|nODGwJoZ-Fc#Qdo!!k>Lht1KZ(WYwOS-jx7#vz_Pe~=|9v5{8@Fa%UG=)d zbf#q}=Z1=NpPp(@(}^q+uG_B{8~r_G=TiPx?frE+Di0<$2rK;w`6n{-R-${~Gu0%o z4Xr(#*Fsbpisc-%9Zyf1G%4@E`fP)E5AD@|vm&FnSM&(*rhaJ?`d4T>XGUCyiiBfW zhMebz_h)qfiEVW8S;(-3X^T%eEnrdVytehUtr6uHmtz z+;xBdG_i8$-QSYy@7%WSo3GKVQ%cvHr80Jwd|^p9bKfV)X#0N6rCa>1U(-Bv*Zn!# zw)Xby4%sA+w3k&gb+1mf_gZ{F-C%yyj)I44XXsy&K6qzy;qiCZ=KfrI|I~$Rd#A=; z{&4&d+v!T*=BGi4i=Qf`e{1ctE$b35dOhpkjKHwpV$-bG=T?+VmyG;rWa#`x!1>6e zGgGvx>)!`9oVyU~`g*HL_WaEm7j?a->#0umY_c{iKRe&P{_(8n{L?#s6J5vVM{lGBa5Zx&;MYntP-xAx-FCs!{Ogt33OI8!F?3E*xnMYYV#^ zB=+o@Wr)~B9#7A5Ro(b~a>eH9VQIF88yc#rQ=B#^8g7b8dlset^a-a)=(p9?Ub--C*H(N%=qwInpfj*H6`*(!SmG)9hzw_F44*cbeJxGtRc|(Bb#~EtPpr u1s3mo&RBeCp4eo(`!F%nzq+5k{r6k-fl(+TsfdArfx*+&&t;ucLK6TWRKgAb literal 10082 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 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..9c43fc9070a9af80aeb10742a82b98234aebe636 GIT binary patch literal 13377 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 UO4e^-U|?YIboFyt=akR{0OWhu&;S4c literal 0 HcmV?d00001 diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..70daa76 --- /dev/null +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #758F9A + diff --git a/ic_web.png b/ic_web.png index 509177f209a872cdd4a23514d381904cc2485810..d54b6ecb4bfa3743c0df4af864f1051b919b1ba1 100644 GIT binary patch literal 27656 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 literal 25559 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 Date: Fri, 19 Apr 2019 10:52:10 -0700 Subject: [PATCH 40/42] Increment version code --- dependencies.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dependencies.gradle b/dependencies.gradle index f98d99e..e0e2412 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -4,7 +4,7 @@ ext.versions = [ compileSdk : 28, buildTools : '28.0.3', publishVersion : '0.8.8', - publishVersionCode : 45, + publishVersionCode : 46, // Plugins gradlePlugin : '3.4.0', From dd9aec1dff1b568f525bd35be164fb7d597b396c Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Mon, 24 Feb 2020 11:50:05 -0800 Subject: [PATCH 41/42] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 156123f..84ee16c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ ## Nock Nock -[![Build Status](https://travis-ci.org/afollestad/nock-nock.svg)](https://travis-ci.org/afollestad/nock-nock) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0.html) ![Showcase](https://raw.githubusercontent.com/afollestad/nock-nock/master/art/showcase5.png) From 23ba4a69cd2b91cb2cb348a1dccf9107f4c516f9 Mon Sep 17 00:00:00 2001 From: Aidan Follestad Date: Mon, 24 Feb 2020 11:50:16 -0800 Subject: [PATCH 42/42] Delete .travis.yml --- .travis.yml | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 15f5e8e..0000000 --- a/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -language: android -jdk: oraclejdk8 - -android: - components: - - tools - - platform-tools - - build-tools-28.0.3 - - android-24 - - android-28 - - sys-img-armeabi-v7a-android-24 - - licenses: - - '.+' - -env: - global: - # install timeout in minutes (2 minutes by default) - - ADB_INSTALL_TIMEOUT=8 - - -# Emulator Management: Create, Start and Wait -before_script: - - echo no | android create avd --force -n test -t android-24 --abi default/armeabi-v7a - - emulator -avd test -no-window & - - android-wait-for-emulator - - adb shell input keyevent 82 & - - -script: - - ./gradlew build connectedCheck