Various fixes and behavioral tweaks

This commit is contained in:
Aidan Follestad 2018-11-30 10:45:22 -08:00
commit c7a8148d3c
6 changed files with 611 additions and 538 deletions

View file

@ -38,6 +38,7 @@ import com.afollestad.nocknock.utilities.ext.textAsLong
import com.afollestad.nocknock.utilities.ext.trimmedText import com.afollestad.nocknock.utilities.ext.trimmedText
import kotlinx.android.synthetic.main.activity_addsite.checkIntervalInput import kotlinx.android.synthetic.main.activity_addsite.checkIntervalInput
import kotlinx.android.synthetic.main.activity_addsite.checkIntervalSpinner import kotlinx.android.synthetic.main.activity_addsite.checkIntervalSpinner
import kotlinx.android.synthetic.main.activity_addsite.content_loading_progress
import kotlinx.android.synthetic.main.activity_addsite.doneBtn import kotlinx.android.synthetic.main.activity_addsite.doneBtn
import kotlinx.android.synthetic.main.activity_addsite.inputName import kotlinx.android.synthetic.main.activity_addsite.inputName
import kotlinx.android.synthetic.main.activity_addsite.inputUrl import kotlinx.android.synthetic.main.activity_addsite.inputUrl
@ -199,7 +200,6 @@ class AddSiteActivity : AppCompatActivity(), View.OnClickListener {
// Done button // Done button
override fun onClick(view: View) { override fun onClick(view: View) {
isClosing = true isClosing = true
var model = ServerModel( var model = ServerModel(
name = inputName.trimmedText(), name = inputName.trimmedText(),
url = inputUrl.trimmedText(), url = inputUrl.trimmedText(),
@ -259,13 +259,20 @@ class AddSiteActivity : AppCompatActivity(), View.OnClickListener {
validationContent = responseValidationScriptInput.trimmedText() validationContent = responseValidationScriptInput.trimmedText()
) )
} }
else -> {
throw IllegalStateException(
"Unexpected validation mode index: ${responseValidationMode.selectedItemPosition}"
)
}
} }
rootView.scopeWhileAttached(Main) { rootView.scopeWhileAttached(Main) {
launch(coroutineContext) { launch(coroutineContext) {
content_loading_progress.show()
val storedModel = async(IO) { serverModelStore.put(model) }.await() val storedModel = async(IO) { serverModelStore.put(model) }.await()
checkStatusManager.cancelCheck(storedModel) checkStatusManager.cancelCheck(storedModel)
checkStatusManager.scheduleCheck(storedModel, rightNow = true) checkStatusManager.scheduleCheck(storedModel, rightNow = true)
content_loading_progress.hide()
setResult(RESULT_OK) setResult(RESULT_OK)
finish() finish()

View file

@ -85,6 +85,7 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
when (intent.action) { when (intent.action) {
ACTION_STATUS_UPDATE -> { ACTION_STATUS_UPDATE -> {
val model = intent.getSerializableExtra(KEY_UPDATE_MODEL) as? ServerModel ?: return val model = intent.getSerializableExtra(KEY_UPDATE_MODEL) as? ServerModel ?: return
log("Received model update: $model")
list.post { adapter.update(model) } list.post { adapter.update(model) }
} }
else -> throw IllegalStateException("Unexpected intent: ${intent.action}") else -> throw IllegalStateException("Unexpected intent: ${intent.action}")

View file

@ -24,6 +24,7 @@ import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.nocknock.BuildConfig import com.afollestad.nocknock.BuildConfig
import com.afollestad.nocknock.R import com.afollestad.nocknock.R
import com.afollestad.nocknock.data.ServerModel import com.afollestad.nocknock.data.ServerModel
import com.afollestad.nocknock.data.ServerStatus.CHECKING
import com.afollestad.nocknock.data.ServerStatus.WAITING import com.afollestad.nocknock.data.ServerStatus.WAITING
import com.afollestad.nocknock.data.ValidationMode.JAVASCRIPT import com.afollestad.nocknock.data.ValidationMode.JAVASCRIPT
import com.afollestad.nocknock.data.ValidationMode.STATUS_CODE import com.afollestad.nocknock.data.ValidationMode.STATUS_CODE
@ -42,6 +43,8 @@ import com.afollestad.nocknock.utilities.ext.hide
import com.afollestad.nocknock.utilities.ext.injector import com.afollestad.nocknock.utilities.ext.injector
import com.afollestad.nocknock.utilities.ext.isHttpOrHttps import com.afollestad.nocknock.utilities.ext.isHttpOrHttps
import com.afollestad.nocknock.utilities.ext.onItemSelected import com.afollestad.nocknock.utilities.ext.onItemSelected
import com.afollestad.nocknock.utilities.ext.safeRegisterReceiver
import com.afollestad.nocknock.utilities.ext.safeUnregisterReceiver
import com.afollestad.nocknock.utilities.ext.scopeWhileAttached import com.afollestad.nocknock.utilities.ext.scopeWhileAttached
import com.afollestad.nocknock.utilities.ext.show import com.afollestad.nocknock.utilities.ext.show
import com.afollestad.nocknock.utilities.ext.showOrHide import com.afollestad.nocknock.utilities.ext.showOrHide
@ -49,6 +52,7 @@ import com.afollestad.nocknock.utilities.ext.textAsLong
import com.afollestad.nocknock.utilities.ext.trimmedText import com.afollestad.nocknock.utilities.ext.trimmedText
import kotlinx.android.synthetic.main.activity_viewsite.checkIntervalInput import kotlinx.android.synthetic.main.activity_viewsite.checkIntervalInput
import kotlinx.android.synthetic.main.activity_viewsite.checkIntervalSpinner import kotlinx.android.synthetic.main.activity_viewsite.checkIntervalSpinner
import kotlinx.android.synthetic.main.activity_viewsite.content_loading_progress
import kotlinx.android.synthetic.main.activity_viewsite.doneBtn import kotlinx.android.synthetic.main.activity_viewsite.doneBtn
import kotlinx.android.synthetic.main.activity_viewsite.iconStatus import kotlinx.android.synthetic.main.activity_viewsite.iconStatus
import kotlinx.android.synthetic.main.activity_viewsite.inputName import kotlinx.android.synthetic.main.activity_viewsite.inputName
@ -106,7 +110,8 @@ class ViewSiteActivity : AppCompatActivity(),
val model = intent.getSerializableExtra(KEY_VIEW_MODEL) as? ServerModel val model = intent.getSerializableExtra(KEY_VIEW_MODEL) as? ServerModel
if (model != null) { if (model != null) {
this@ViewSiteActivity.currentModel = model this@ViewSiteActivity.currentModel = model
update() log("Received model update: $currentModel")
displayCurrentModel()
} }
} }
} }
@ -177,19 +182,19 @@ class ViewSiteActivity : AppCompatActivity(),
} }
currentModel = intent.getSerializableExtra(KEY_VIEW_MODEL) as ServerModel currentModel = intent.getSerializableExtra(KEY_VIEW_MODEL) as ServerModel
update() displayCurrentModel()
} }
override fun onNewIntent(intent: Intent?) { override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent) super.onNewIntent(intent)
if (intent != null && intent.hasExtra(KEY_VIEW_MODEL)) { if (intent != null && intent.hasExtra(KEY_VIEW_MODEL)) {
currentModel = intent.getSerializableExtra(KEY_VIEW_MODEL) as ServerModel currentModel = intent.getSerializableExtra(KEY_VIEW_MODEL) as ServerModel
update() displayCurrentModel()
} }
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun update() = with(currentModel) { private fun displayCurrentModel() = with(currentModel) {
iconStatus.setStatus(this.status) iconStatus.setStatus(this.status)
inputName.setText(this.name) inputName.setText(this.name)
inputUrl.setText(this.url) inputUrl.setText(this.url)
@ -260,27 +265,20 @@ class ViewSiteActivity : AppCompatActivity(),
} }
doneBtn.setOnClickListener(this@ViewSiteActivity) doneBtn.setOnClickListener(this@ViewSiteActivity)
invalidateMenuForStatus()
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
try { val filter = IntentFilter().apply {
val filter = IntentFilter() addAction(ACTION_STATUS_UPDATE)
filter.addAction(ACTION_STATUS_UPDATE)
// filter.addAction(CheckService.ACTION_JOB_RUNNING);
registerReceiver(intentReceiver, filter)
} catch (t: Throwable) {
t.printStackTrace()
} }
safeRegisterReceiver(intentReceiver, filter)
} }
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
try { safeUnregisterReceiver(intentReceiver)
unregisterReceiver(intentReceiver)
} catch (t: Throwable) {
t.printStackTrace()
}
} }
private fun updateModelFromInput(withValidation: Boolean) { private fun updateModelFromInput(withValidation: Boolean) {
@ -345,6 +343,11 @@ class ViewSiteActivity : AppCompatActivity(),
validationContent = responseValidationScriptInput.trimmedText() validationContent = responseValidationScriptInput.trimmedText()
) )
} }
else -> {
throw IllegalStateException(
"Unexpected response validation mode index: ${responseValidationMode.selectedItemPosition}"
)
}
} }
} }
@ -352,8 +355,14 @@ class ViewSiteActivity : AppCompatActivity(),
override fun onClick(view: View) { override fun onClick(view: View) {
rootView.scopeWhileAttached(Main) { rootView.scopeWhileAttached(Main) {
launch(coroutineContext) { launch(coroutineContext) {
content_loading_progress.show()
updateModelFromInput(true) updateModelFromInput(true)
async(IO) { serverModelStore.update(currentModel) }.await() async(IO) { serverModelStore.update(currentModel) }.await()
checkStatusManager.cancelCheck(currentModel)
checkStatusManager.scheduleCheck(currentModel, rightNow = true)
content_loading_progress.hide()
setResult(RESULT_OK) setResult(RESULT_OK)
finish() finish()
} }
@ -365,26 +374,29 @@ class ViewSiteActivity : AppCompatActivity(),
R.id.refresh -> { R.id.refresh -> {
rootView.scopeWhileAttached(Main) { rootView.scopeWhileAttached(Main) {
launch(coroutineContext) { launch(coroutineContext) {
content_loading_progress.show()
updateModelFromInput(false) updateModelFromInput(false)
currentModel = currentModel.copy(status = WAITING)
displayCurrentModel()
async(IO) { serverModelStore.update(currentModel) }.await() async(IO) { serverModelStore.update(currentModel) }.await()
checkStatusManager.cancelCheck(currentModel) checkStatusManager.cancelCheck(currentModel)
checkStatusManager.scheduleCheck(currentModel, rightNow = true) checkStatusManager.scheduleCheck(currentModel, rightNow = true)
content_loading_progress.hide()
} }
} }
return true return true
} }
R.id.remove -> { R.id.remove -> {
maybeRemoveSite(currentModel) { finish() } maybeRemoveSite(currentModel)
return true return true
} }
} }
return false return false
} }
private fun maybeRemoveSite( private fun maybeRemoveSite(model: ServerModel) {
model: ServerModel,
onRemoved: (() -> Unit)?
) {
MaterialDialog(this).show { MaterialDialog(this).show {
title(R.string.remove_site) title(R.string.remove_site)
message( message(
@ -396,21 +408,25 @@ class ViewSiteActivity : AppCompatActivity(),
positiveButton(R.string.remove) { positiveButton(R.string.remove) {
checkStatusManager.cancelCheck(model) checkStatusManager.cancelCheck(model)
notificationManager.cancelStatusNotifications() notificationManager.cancelStatusNotifications()
performRemoveSite(model, onRemoved) performRemoveSite(model)
} }
negativeButton(android.R.string.cancel) negativeButton(android.R.string.cancel)
} }
} }
private fun performRemoveSite( private fun performRemoveSite(model: ServerModel) {
model: ServerModel,
onRemoved: (() -> Unit)?
) {
rootView.scopeWhileAttached(Main) { rootView.scopeWhileAttached(Main) {
launch(coroutineContext) { launch(coroutineContext) {
content_loading_progress.show()
async(IO) { serverModelStore.delete(model) }.await() async(IO) { serverModelStore.delete(model) }.await()
onRemoved?.invoke() content_loading_progress.hide()
finish()
} }
} }
} }
private fun invalidateMenuForStatus() {
val item = toolbar.menu.findItem(R.id.refresh)
item.isEnabled = currentModel.status != CHECKING && currentModel.status != WAITING
}
} }

View file

@ -1,8 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:id="@+id/rootView" android:id="@+id/rootView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -267,4 +272,23 @@
</ScrollView> </ScrollView>
</LinearLayout> </LinearLayout>
<FrameLayout
android:id="@+id/content_loading_progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#40000000"
android:visibility="gone"
>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
style="?android:progressBarStyleLarge"
/>
</FrameLayout>
</FrameLayout>

View file

@ -1,7 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:id="@+id/rootView" android:id="@+id/rootView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -229,7 +235,6 @@
android:background="@null" android:background="@null"
android:fontFamily="serif-monospace" android:fontFamily="serif-monospace"
android:gravity="top" android:gravity="top"
android:hint="@string/default_js"
android:inputType="textMultiLine" android:inputType="textMultiLine"
android:lineSpacingMultiplier="1.4" android:lineSpacingMultiplier="1.4"
android:paddingBottom="@dimen/content_inset_less" android:paddingBottom="@dimen/content_inset_less"
@ -237,8 +242,9 @@
android:paddingStart="@dimen/content_inset_more" android:paddingStart="@dimen/content_inset_more"
android:paddingTop="@dimen/content_inset_less" android:paddingTop="@dimen/content_inset_less"
android:scrollHorizontally="true" android:scrollHorizontally="true"
android:text="@string/default_js"
android:textSize="@dimen/code_font_size" android:textSize="@dimen/code_font_size"
tools:ignore="Autofill,LabelFor,RtlSymmetry" tools:ignore="Autofill,LabelFor"
/> />
<TextView <TextView
@ -326,4 +332,23 @@
</ScrollView> </ScrollView>
</LinearLayout> </LinearLayout>
<FrameLayout
android:id="@+id/content_loading_progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#40000000"
android:visibility="gone"
>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
style="?android:progressBarStyleLarge"
/>
</FrameLayout>
</FrameLayout>

View file

@ -160,7 +160,7 @@ class CheckStatusJob : JobService() {
modelStore.update(newSiteModel) modelStore.update(newSiteModel)
withContext(Main) { withContext(Main) {
sendBroadcast(Intent(ACTION_STATUS_UPDATE).apply { putExtra(KEY_UPDATE_MODEL, site) }) sendBroadcast(Intent(ACTION_STATUS_UPDATE).apply { putExtra(KEY_UPDATE_MODEL, newSiteModel) })
} }
return newSiteModel return newSiteModel
} }