mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-21 05:53:12 -07:00
Handle Duplicate Registered Host on Android
This commit is contained in:
parent
da73d4e26e
commit
98f9f3f6e9
6 changed files with 74 additions and 24 deletions
|
@ -20,6 +20,7 @@ package com.metallic.chiaki.common
|
||||||
import androidx.room.*
|
import androidx.room.*
|
||||||
import androidx.room.ColumnInfo.BLOB
|
import androidx.room.ColumnInfo.BLOB
|
||||||
import com.metallic.chiaki.lib.RegistHost
|
import com.metallic.chiaki.lib.RegistHost
|
||||||
|
import io.reactivex.Completable
|
||||||
import io.reactivex.Flowable
|
import io.reactivex.Flowable
|
||||||
import io.reactivex.Maybe
|
import io.reactivex.Maybe
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
@ -61,6 +62,9 @@ interface RegisteredHostDao
|
||||||
@Query("SELECT * FROM registered_host WHERE ps4_mac == :mac LIMIT 1")
|
@Query("SELECT * FROM registered_host WHERE ps4_mac == :mac LIMIT 1")
|
||||||
fun getByMac(mac: MacAddress): Maybe<RegisteredHost>
|
fun getByMac(mac: MacAddress): Maybe<RegisteredHost>
|
||||||
|
|
||||||
|
@Query("DELETE FROM registered_host WHERE ps4_mac == :mac")
|
||||||
|
fun deleteByMac(mac: MacAddress): Completable
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
fun insert(host: RegisteredHost): Single<Long>
|
fun insert(host: RegisteredHost): Single<Long>
|
||||||
}
|
}
|
|
@ -18,6 +18,8 @@
|
||||||
package com.metallic.chiaki.regist
|
package com.metallic.chiaki.regist
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.app.AlertDialog
|
||||||
|
import android.content.DialogInterface
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.method.ScrollingMovementMethod
|
import android.text.method.ScrollingMovementMethod
|
||||||
|
@ -26,6 +28,7 @@ import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.lifecycle.ViewModelProviders
|
import androidx.lifecycle.ViewModelProviders
|
||||||
import com.metallic.chiaki.R
|
import com.metallic.chiaki.R
|
||||||
|
import com.metallic.chiaki.common.MacAddress
|
||||||
import com.metallic.chiaki.common.ext.viewModelFactory
|
import com.metallic.chiaki.common.ext.viewModelFactory
|
||||||
import com.metallic.chiaki.common.getDatabase
|
import com.metallic.chiaki.common.getDatabase
|
||||||
import com.metallic.chiaki.lib.RegistInfo
|
import com.metallic.chiaki.lib.RegistInfo
|
||||||
|
@ -70,11 +73,13 @@ class RegistExecuteActivity: AppCompatActivity()
|
||||||
infoTextView.setText(R.string.regist_info_failed)
|
infoTextView.setText(R.string.regist_info_failed)
|
||||||
setResult(RESULT_FAILED)
|
setResult(RESULT_FAILED)
|
||||||
}
|
}
|
||||||
RegistExecuteViewModel.State.SUCCESSFUL ->
|
RegistExecuteViewModel.State.SUCCESSFUL, RegistExecuteViewModel.State.SUCCESSFUL_DUPLICATE ->
|
||||||
{
|
{
|
||||||
infoTextView.visibility = View.VISIBLE
|
infoTextView.visibility = View.VISIBLE
|
||||||
infoTextView.setText(R.string.regist_info_success)
|
infoTextView.setText(R.string.regist_info_success)
|
||||||
setResult(RESULT_OK)
|
setResult(RESULT_OK)
|
||||||
|
if(it == RegistExecuteViewModel.State.SUCCESSFUL_DUPLICATE)
|
||||||
|
showDuplicateDialog()
|
||||||
}
|
}
|
||||||
RegistExecuteViewModel.State.STOPPED ->
|
RegistExecuteViewModel.State.STOPPED ->
|
||||||
{
|
{
|
||||||
|
@ -108,4 +113,24 @@ class RegistExecuteActivity: AppCompatActivity()
|
||||||
super.onStop()
|
super.onStop()
|
||||||
viewModel.stop()
|
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() }
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -18,7 +18,6 @@
|
||||||
package com.metallic.chiaki.regist
|
package com.metallic.chiaki.regist
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.lifecycle.AndroidViewModel
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
@ -29,6 +28,7 @@ import com.metallic.chiaki.common.ext.toLiveData
|
||||||
import com.metallic.chiaki.lib.*
|
import com.metallic.chiaki.lib.*
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
|
import io.reactivex.functions.Action
|
||||||
import io.reactivex.rxkotlin.addTo
|
import io.reactivex.rxkotlin.addTo
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
|
||||||
|
@ -40,7 +40,8 @@ class RegistExecuteViewModel(val database: AppDatabase): ViewModel()
|
||||||
RUNNING,
|
RUNNING,
|
||||||
STOPPED,
|
STOPPED,
|
||||||
FAILED,
|
FAILED,
|
||||||
SUCCESSFUL
|
SUCCESSFUL,
|
||||||
|
SUCCESSFUL_DUPLICATE,
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _state = MutableLiveData<State>(State.IDLE)
|
private val _state = MutableLiveData<State>(State.IDLE)
|
||||||
|
@ -53,6 +54,9 @@ class RegistExecuteViewModel(val database: AppDatabase): ViewModel()
|
||||||
|
|
||||||
private val disposable = CompositeDisposable()
|
private val disposable = CompositeDisposable()
|
||||||
|
|
||||||
|
var host: RegistHost? = null
|
||||||
|
private set
|
||||||
|
|
||||||
fun start(info: RegistInfo)
|
fun start(info: RegistInfo)
|
||||||
{
|
{
|
||||||
if(regist != null)
|
if(regist != null)
|
||||||
|
@ -86,28 +90,33 @@ class RegistExecuteViewModel(val database: AppDatabase): ViewModel()
|
||||||
|
|
||||||
private fun registSuccess(host: RegistHost)
|
private fun registSuccess(host: RegistHost)
|
||||||
{
|
{
|
||||||
_state.postValue(State.SUCCESSFUL) // TODO: more states
|
this.host = host
|
||||||
|
database.registeredHostDao().getByMac(MacAddress(host.ps4Mac))
|
||||||
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)
|
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.doOnSuccess {
|
.doOnSuccess {
|
||||||
// TODO: show dialog
|
_state.value = State.SUCCESSFUL_DUPLICATE
|
||||||
Log.i("RegistExecuteViewModel", "already exists")
|
|
||||||
}
|
}
|
||||||
.doOnComplete {
|
.doOnComplete {
|
||||||
dao.insert(RegisteredHost(host))
|
saveHost()
|
||||||
.subscribeOn(Schedulers.io())
|
}
|
||||||
.subscribe()
|
.subscribe()
|
||||||
.addTo(disposable)
|
.addTo(disposable)
|
||||||
}
|
}
|
||||||
.subscribe()
|
|
||||||
|
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)
|
.addTo(disposable)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,8 +126,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="textNoSuggestions|textVisiblePassword"
|
android:inputType="textNoSuggestions|textVisiblePassword"
|
||||||
android:maxLines="1"
|
android:maxLines="1"/>
|
||||||
android:text="test"/>
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
@ -175,8 +174,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
android:maxLength="8"
|
android:maxLength="8"/>
|
||||||
android:text="01234567"/>
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
|
|
|
@ -35,4 +35,7 @@
|
||||||
<string name="action_share_log">Share Log</string>
|
<string name="action_share_log">Share Log</string>
|
||||||
<string name="regist_info_success">Regist successful.</string>
|
<string name="regist_info_success">Regist successful.</string>
|
||||||
<string name="regist_info_failed">Regist failed.</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>
|
</resources>
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<item name="android:navigationBarColor">?attr/colorPrimarySurface</item>
|
<item name="android:navigationBarColor">?attr/colorPrimarySurface</item>
|
||||||
<item name="colorControlNormal">@color/accent</item>
|
<item name="colorControlNormal">@color/accent</item>
|
||||||
<item name="colorButtonNormal">@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="android:textColor">?attr/colorOnPrimary</item>
|
||||||
|
|
||||||
<item name="textAppearanceHeadline1">@style/MageTheme.TextAppearanceHeadline1</item>
|
<item name="textAppearanceHeadline1">@style/MageTheme.TextAppearanceHeadline1</item>
|
||||||
|
@ -47,6 +47,8 @@
|
||||||
|
|
||||||
<item name="android:windowActivityTransitions">true</item>
|
<item name="android:windowActivityTransitions">true</item>
|
||||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||||
|
|
||||||
|
<item name="android:alertDialogTheme">@style/MageTheme.AlertDialog</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="MageTheme.Translucent" parent="MageTheme">
|
<style name="MageTheme.Translucent" parent="MageTheme">
|
||||||
|
@ -57,6 +59,15 @@
|
||||||
<item name="fontFamily">sans-serif-condensed-light</item>
|
<item name="fontFamily">sans-serif-condensed-light</item>
|
||||||
</style>
|
</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">
|
<style name="MageTheme.TextInputStyle" parent="Widget.MaterialComponents.TextInputLayout.FilledBox">
|
||||||
<item name="hintTextColor">?attr/colorAccent</item>
|
<item name="hintTextColor">?attr/colorAccent</item>
|
||||||
<item name="boxCornerRadiusTopStart">16dp</item>
|
<item name="boxCornerRadiusTopStart">16dp</item>
|
||||||
|
@ -72,7 +83,7 @@
|
||||||
<item name="iconTint">?attr/colorOnSecondary</item>
|
<item name="iconTint">?attr/colorOnSecondary</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="TextAppearanceButton" parent="TextAppearance.MaterialComponents.Button">
|
<style name="MageTheme.TextAppearanceButton" parent="TextAppearance.MaterialComponents.Button">
|
||||||
<item name="android:textColor">?attr/colorOnSecondary</item>
|
<item name="android:textColor">?attr/colorOnSecondary</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue