Handle Duplicate Registered Host on Android

This commit is contained in:
Florian Märkl 2019-10-16 15:47:15 +02:00
commit 98f9f3f6e9
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
6 changed files with 74 additions and 24 deletions

View file

@ -20,6 +20,7 @@ package com.metallic.chiaki.common
import androidx.room.*
import androidx.room.ColumnInfo.BLOB
import com.metallic.chiaki.lib.RegistHost
import io.reactivex.Completable
import io.reactivex.Flowable
import io.reactivex.Maybe
import io.reactivex.Single
@ -61,6 +62,9 @@ interface RegisteredHostDao
@Query("SELECT * FROM registered_host WHERE ps4_mac == :mac LIMIT 1")
fun getByMac(mac: MacAddress): Maybe<RegisteredHost>
@Query("DELETE FROM registered_host WHERE ps4_mac == :mac")
fun deleteByMac(mac: MacAddress): Completable
@Insert
fun insert(host: RegisteredHost): Single<Long>
}

View file

@ -18,6 +18,8 @@
package com.metallic.chiaki.regist
import android.app.Activity
import android.app.AlertDialog
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import android.text.method.ScrollingMovementMethod
@ -26,6 +28,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import com.metallic.chiaki.R
import com.metallic.chiaki.common.MacAddress
import com.metallic.chiaki.common.ext.viewModelFactory
import com.metallic.chiaki.common.getDatabase
import com.metallic.chiaki.lib.RegistInfo
@ -70,11 +73,13 @@ class RegistExecuteActivity: AppCompatActivity()
infoTextView.setText(R.string.regist_info_failed)
setResult(RESULT_FAILED)
}
RegistExecuteViewModel.State.SUCCESSFUL ->
RegistExecuteViewModel.State.SUCCESSFUL, RegistExecuteViewModel.State.SUCCESSFUL_DUPLICATE ->
{
infoTextView.visibility = View.VISIBLE
infoTextView.setText(R.string.regist_info_success)
setResult(RESULT_OK)
if(it == RegistExecuteViewModel.State.SUCCESSFUL_DUPLICATE)
showDuplicateDialog()
}
RegistExecuteViewModel.State.STOPPED ->
{
@ -108,4 +113,24 @@ class RegistExecuteActivity: AppCompatActivity()
super.onStop()
viewModel.stop()
}
private var dialog: AlertDialog? = null
private fun showDuplicateDialog()
{
if(dialog != null)
return
val macStr = viewModel.host?.ps4Mac?.let { MacAddress(it).toString() } ?: ""
dialog = AlertDialog.Builder(this)
.setMessage(getString(R.string.alert_regist_duplicate, macStr))
.setNegativeButton(R.string.action_regist_discard) { _, _ -> }
.setPositiveButton(R.string.action_regist_overwrite) { _, _ ->
viewModel.saveHost()
}
.create()
.also { it.show() }
}
}

View file

@ -18,7 +18,6 @@
package com.metallic.chiaki.regist
import android.util.Log
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
@ -29,6 +28,7 @@ import com.metallic.chiaki.common.ext.toLiveData
import com.metallic.chiaki.lib.*
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.functions.Action
import io.reactivex.rxkotlin.addTo
import io.reactivex.schedulers.Schedulers
@ -40,7 +40,8 @@ class RegistExecuteViewModel(val database: AppDatabase): ViewModel()
RUNNING,
STOPPED,
FAILED,
SUCCESSFUL
SUCCESSFUL,
SUCCESSFUL_DUPLICATE,
}
private val _state = MutableLiveData<State>(State.IDLE)
@ -53,6 +54,9 @@ class RegistExecuteViewModel(val database: AppDatabase): ViewModel()
private val disposable = CompositeDisposable()
var host: RegistHost? = null
private set
fun start(info: RegistInfo)
{
if(regist != null)
@ -86,31 +90,36 @@ class RegistExecuteViewModel(val database: AppDatabase): ViewModel()
private fun registSuccess(host: RegistHost)
{
_state.postValue(State.SUCCESSFUL) // TODO: more states
val dao = database.registeredHostDao()
val mac = MacAddress(host.ps4Mac)
//val mac = MacAddress(byteArrayOf(0xc0.toByte(), 0xff.toByte(), 0xff.toByte(), 0xee.toByte(), 0xee.toByte(), 0x42))
dao.getByMac(mac)
this.host = host
database.registeredHostDao().getByMac(MacAddress(host.ps4Mac))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSuccess {
// TODO: show dialog
Log.i("RegistExecuteViewModel", "already exists")
_state.value = State.SUCCESSFUL_DUPLICATE
}
.doOnComplete {
dao.insert(RegisteredHost(host))
.subscribeOn(Schedulers.io())
.subscribe()
.addTo(disposable)
saveHost()
}
.subscribe()
.addTo(disposable)
}
fun saveHost()
{
val host = host ?: return
val dao = database.registeredHostDao()
val registeredHost = RegisteredHost(host)
dao.deleteByMac(registeredHost.ps4Mac)
.andThen(dao.insert(registeredHost))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { _ ->
Log.i("RegistExecute", "Registered Host saved in db")
_state.value = State.SUCCESSFUL
}
.addTo(disposable)
}
override fun onCleared()
{
super.onCleared()

View file

@ -126,8 +126,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textNoSuggestions|textVisiblePassword"
android:maxLines="1"
android:text="test"/>
android:maxLines="1"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textview.MaterialTextView
@ -175,8 +174,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:maxLength="8"
android:text="01234567"/>
android:maxLength="8"/>
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton

View file

@ -35,4 +35,7 @@
<string name="action_share_log">Share Log</string>
<string name="regist_info_success">Regist successful.</string>
<string name="regist_info_failed">Regist failed.</string>
<string name="alert_regist_duplicate">The console with MAC %s has already been registered. Should the previous record be overwritten?</string>
<string name="action_regist_overwrite">Overwrite</string>
<string name="action_regist_discard">Cancel</string>
</resources>

View file

@ -35,7 +35,7 @@
<item name="android:navigationBarColor">?attr/colorPrimarySurface</item>
<item name="colorControlNormal">@color/accent</item>
<item name="colorButtonNormal">@color/accent</item>
<item name="android:textAppearanceButton">@style/TextAppearanceButton</item>
<item name="android:textAppearanceButton">@style/MageTheme.TextAppearanceButton</item>
<item name="android:textColor">?attr/colorOnPrimary</item>
<item name="textAppearanceHeadline1">@style/MageTheme.TextAppearanceHeadline1</item>
@ -47,6 +47,8 @@
<item name="android:windowActivityTransitions">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:alertDialogTheme">@style/MageTheme.AlertDialog</item>
</style>
<style name="MageTheme.Translucent" parent="MageTheme">
@ -57,6 +59,15 @@
<item name="fontFamily">sans-serif-condensed-light</item>
</style>
<style name="MageTheme.AlertDialog" parent="Theme.MaterialComponents.Dialog.Alert">
<item name="android:textColorPrimary">@android:color/primary_text_light</item>
<item name="materialButtonStyle">@style/MageTheme.AlertDialog.Button</item>
</style>
<style name="MageTheme.AlertDialog.Button" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
<item name="android:textColor">@color/accent</item>
</style>
<style name="MageTheme.TextInputStyle" parent="Widget.MaterialComponents.TextInputLayout.FilledBox">
<item name="hintTextColor">?attr/colorAccent</item>
<item name="boxCornerRadiusTopStart">16dp</item>
@ -72,7 +83,7 @@
<item name="iconTint">?attr/colorOnSecondary</item>
</style>
<style name="TextAppearanceButton" parent="TextAppearance.MaterialComponents.Button">
<style name="MageTheme.TextAppearanceButton" parent="TextAppearance.MaterialComponents.Button">
<item name="android:textColor">?attr/colorOnSecondary</item>
</style>