From 6baf8e9c2a7e9510acc723df45879e9f9ae60d54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Fri, 25 Oct 2019 18:58:34 +0200 Subject: [PATCH] Add Manual Consoles on Android --- android/app/src/main/AndroidManifest.xml | 14 ++- .../com/metallic/chiaki/TestStartActivity.kt | 86 -------------- .../com/metallic/chiaki/main/MainActivity.kt | 6 +- .../manualconsole/AddManualConsoleActivity.kt | 106 ++++++++++++++++++ .../AddManualConsoleViewModel.kt | 48 ++++++++ .../metallic/chiaki/regist/RegistActivity.kt | 3 +- .../chiaki/regist/RegistExecuteActivity.kt | 3 - .../chiaki/regist/RegistExecuteViewModel.kt | 3 +- .../src/main/res/drawable/ic_add_manual.xml | 23 ++++ .../main/res/layout/activity_add_manual.xml | 83 ++++++++++++++ .../main/res/layout/activity_test_start.xml | 56 --------- .../res/layout/dropdown_menu_popup_item.xml | 8 ++ android/app/src/main/res/values/strings.xml | 6 +- android/app/src/main/res/values/styles.xml | 8 ++ assets/add_console.svg | 81 +++++++++++++ 15 files changed, 374 insertions(+), 160 deletions(-) delete mode 100644 android/app/src/main/java/com/metallic/chiaki/TestStartActivity.kt create mode 100644 android/app/src/main/java/com/metallic/chiaki/manualconsole/AddManualConsoleActivity.kt create mode 100644 android/app/src/main/java/com/metallic/chiaki/manualconsole/AddManualConsoleViewModel.kt create mode 100644 android/app/src/main/res/drawable/ic_add_manual.xml create mode 100644 android/app/src/main/res/layout/activity_add_manual.xml delete mode 100644 android/app/src/main/res/layout/activity_test_start.xml create mode 100644 android/app/src/main/res/layout/dropdown_menu_popup_item.xml create mode 100644 assets/add_console.svg diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 326f866..3708e74 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ @@ -11,7 +12,8 @@ android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" - android:theme="@style/AppTheme"> + android:theme="@style/AppTheme" + tools:ignore="GoogleAppIndexingWarning"> @@ -30,11 +32,6 @@ - - + + \ No newline at end of file diff --git a/android/app/src/main/java/com/metallic/chiaki/TestStartActivity.kt b/android/app/src/main/java/com/metallic/chiaki/TestStartActivity.kt deleted file mode 100644 index 6c1e23c..0000000 --- a/android/app/src/main/java/com/metallic/chiaki/TestStartActivity.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is part of Chiaki. - * - * Chiaki is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Chiaki is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Chiaki. If not, see . - */ - -package com.metallic.chiaki - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.util.Base64 -import android.view.View -import android.view.Window -import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.edit -import androidx.core.widget.addTextChangedListener -import com.metallic.chiaki.common.Preferences -import com.metallic.chiaki.common.ext.RevealActivity -import com.metallic.chiaki.lib.ConnectInfo -import com.metallic.chiaki.stream.StreamActivity -import kotlinx.android.synthetic.main.activity_test_start.* - -class TestStartActivity : AppCompatActivity(), RevealActivity -{ - override val revealIntent: Intent get() = intent - override val revealRootLayout: View get() = rootLayout - override val revealWindow: Window get() = window - - override fun onCreate(savedInstanceState: Bundle?) - { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_test_start) - handleReveal() - - val prefs = getPreferences(Context.MODE_PRIVATE) - - hostEditText.setText(prefs.getString("debug_host", "")) - registKeyEditText.setText(prefs.getString("debug_regist_key", "")) - morningEditText.setText(prefs.getString("debug_morning", "")) - - hostEditText.addTextChangedListener { - prefs.edit { - putString("debug_host", it?.toString()) - } - } - - registKeyEditText.addTextChangedListener { - prefs.edit { - putString("debug_regist_key", it?.toString()) - } - } - - morningEditText.addTextChangedListener { - prefs.edit { - putString("debug_morning", it?.toString()) - } - } - - startButton.setOnClickListener { - val registKeyBase = registKeyEditText.text.toString().toByteArray(Charsets.US_ASCII) - val registKey = registKeyBase + ByteArray(0x10 - registKeyBase.size) { 0 } - val morning = Base64.decode(morningEditText.text.toString(), Base64.DEFAULT) - val connectInfo = ConnectInfo(hostEditText.text.toString(), - registKey, - morning, - Preferences(this).videoProfile) - - Intent(this, StreamActivity::class.java).let { - it.putExtra(StreamActivity.EXTRA_CONNECT_INFO, connectInfo) - startActivity(it) - } - } - } -} diff --git a/android/app/src/main/java/com/metallic/chiaki/main/MainActivity.kt b/android/app/src/main/java/com/metallic/chiaki/main/MainActivity.kt index 427af00..0e0dd7b 100644 --- a/android/app/src/main/java/com/metallic/chiaki/main/MainActivity.kt +++ b/android/app/src/main/java/com/metallic/chiaki/main/MainActivity.kt @@ -18,7 +18,6 @@ package com.metallic.chiaki.main import android.app.ActivityOptions -import android.app.AlertDialog import android.content.Intent import android.os.Bundle import android.view.Menu @@ -29,7 +28,6 @@ import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.metallic.chiaki.R -import com.metallic.chiaki.TestStartActivity import com.metallic.chiaki.common.DiscoveredDisplayHost import com.metallic.chiaki.common.DisplayHost import com.metallic.chiaki.common.Preferences @@ -38,7 +36,7 @@ import com.metallic.chiaki.common.ext.viewModelFactory import com.metallic.chiaki.common.getDatabase import com.metallic.chiaki.lib.ConnectInfo import com.metallic.chiaki.lib.DiscoveryHost -import com.metallic.chiaki.lib.RegistEventSuccess +import com.metallic.chiaki.manualconsole.AddManualConsoleActivity import com.metallic.chiaki.regist.RegistActivity import com.metallic.chiaki.settings.SettingsActivity import com.metallic.chiaki.stream.StreamActivity @@ -153,7 +151,7 @@ class MainActivity : AppCompatActivity() private fun addManualConsole() { - Intent(this, TestStartActivity::class.java).also { + Intent(this, AddManualConsoleActivity::class.java).also { it.putRevealExtra(addManualButton, rootLayout) startActivity(it, ActivityOptions.makeSceneTransitionAnimation(this).toBundle()) } diff --git a/android/app/src/main/java/com/metallic/chiaki/manualconsole/AddManualConsoleActivity.kt b/android/app/src/main/java/com/metallic/chiaki/manualconsole/AddManualConsoleActivity.kt new file mode 100644 index 0000000..df5d47d --- /dev/null +++ b/android/app/src/main/java/com/metallic/chiaki/manualconsole/AddManualConsoleActivity.kt @@ -0,0 +1,106 @@ +/* + * This file is part of Chiaki. + * + * Chiaki is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Chiaki is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chiaki. If not, see . + */ + +package com.metallic.chiaki.manualconsole + +import android.content.Intent +import android.os.Bundle +import android.view.View +import android.view.Window +import android.widget.AdapterView +import android.widget.AdapterView.OnItemSelectedListener +import android.widget.ArrayAdapter +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProviders +import com.metallic.chiaki.R +import com.metallic.chiaki.common.ManualHost +import com.metallic.chiaki.common.RegisteredHost +import com.metallic.chiaki.common.ext.RevealActivity +import com.metallic.chiaki.common.ext.viewModelFactory +import com.metallic.chiaki.common.getDatabase +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.addTo +import kotlinx.android.synthetic.main.activity_add_manual.* + +class AddManualConsoleActivity: AppCompatActivity(), RevealActivity +{ + override val revealIntent: Intent get() = intent + override val revealRootLayout: View get() = rootLayout + override val revealWindow: Window get() = window + + private lateinit var viewModel: AddManualConsoleViewModel + + private val disposable = CompositeDisposable() + + override fun onCreate(savedInstanceState: Bundle?) + { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_add_manual) + handleReveal() + + viewModel = ViewModelProviders + .of(this, viewModelFactory { AddManualConsoleViewModel(getDatabase(this)) }) + .get(AddManualConsoleViewModel::class.java) + + viewModel.selectedRegisteredHost.observe(this, Observer { + registeredHostTextView.setText(titleForRegisteredHost(it)) + }) + + viewModel.registeredHosts.observe(this, Observer { hosts -> + registeredHostTextView.setAdapter(ArrayAdapter(this, R.layout.dropdown_menu_popup_item, + hosts.map { titleForRegisteredHost(it) })) + registeredHostTextView.onItemClickListener = object: AdapterView.OnItemClickListener { + override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) + { + if(position >= hosts.size) + return + val host = hosts[position] + viewModel.selectedRegisteredHost.value = host + } + } + }) + + + saveButton.setOnClickListener { saveHost() } + } + + private fun titleForRegisteredHost(registeredHost: RegisteredHost?) = + if(registeredHost == null) + getString(R.string.add_manual_regist_on_connect) + else + "${registeredHost.ps4Nickname ?: ""} (${registeredHost.ps4Mac})" + + private fun saveHost() + { + val host = hostEditText.text.toString().trim() + if(host.isEmpty()) + { + hostEditText.error = getString(R.string.entered_host_invalid) + return + } + + saveButton.isEnabled = false + viewModel.saveHost(host) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { + finish() + } + .addTo(disposable) + } +} \ No newline at end of file diff --git a/android/app/src/main/java/com/metallic/chiaki/manualconsole/AddManualConsoleViewModel.kt b/android/app/src/main/java/com/metallic/chiaki/manualconsole/AddManualConsoleViewModel.kt new file mode 100644 index 0000000..7b0888c --- /dev/null +++ b/android/app/src/main/java/com/metallic/chiaki/manualconsole/AddManualConsoleViewModel.kt @@ -0,0 +1,48 @@ +/* + * This file is part of Chiaki. + * + * Chiaki is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Chiaki is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chiaki. If not, see . + */ + +package com.metallic.chiaki.manualconsole + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.metallic.chiaki.common.AppDatabase +import com.metallic.chiaki.common.ManualHost +import com.metallic.chiaki.common.RegisteredHost +import com.metallic.chiaki.common.ext.toLiveData +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.schedulers.Schedulers + +class AddManualConsoleViewModel(val database: AppDatabase): ViewModel() +{ + val registeredHosts by lazy { + database.registeredHostDao().getAll().observeOn(AndroidSchedulers.mainThread()) + .doOnNext { hosts -> + val selectedHost = selectedRegisteredHost.value + if(selectedHost != null) + selectedRegisteredHost.value = hosts.firstOrNull { it.id == selectedHost.id } + } + .map { listOf(null) + it } + .toLiveData() + } + + var selectedRegisteredHost = MutableLiveData(null) + + fun saveHost(host: String) = + database.manualHostDao() + .insert(ManualHost(host = host, registeredHost = selectedRegisteredHost.value?.id)) + .subscribeOn(Schedulers.io()) +} \ No newline at end of file diff --git a/android/app/src/main/java/com/metallic/chiaki/regist/RegistActivity.kt b/android/app/src/main/java/com/metallic/chiaki/regist/RegistActivity.kt index b79cd74..aaff1db 100644 --- a/android/app/src/main/java/com/metallic/chiaki/regist/RegistActivity.kt +++ b/android/app/src/main/java/com/metallic/chiaki/regist/RegistActivity.kt @@ -20,7 +20,6 @@ package com.metallic.chiaki.regist import android.content.Intent import android.os.Bundle import android.util.Base64 -import android.util.Log import android.view.View import android.view.Window import androidx.appcompat.app.AppCompatActivity @@ -112,7 +111,7 @@ class RegistActivity: AppCompatActivity(), RevealActivity val pin = pinEditText.text.toString() val pinValid = pin.length == PIN_LENGTH - hostEditText.error = if(!hostValid) getString(R.string.regist_host_invalid) else null + hostEditText.error = if(!hostValid) getString(R.string.entered_host_invalid) else null psnIdEditText.error = if(!psnIdValid) getString(when(ps4Version) diff --git a/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt index 869a9f9..9bf06f0 100644 --- a/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt +++ b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteActivity.kt @@ -55,9 +55,6 @@ class RegistExecuteActivity: AppCompatActivity() .of(this, viewModelFactory { RegistExecuteViewModel(getDatabase(this)) }) .get(RegistExecuteViewModel::class.java) - showDuplicateDialog() - return - logTextView.setHorizontallyScrolling(true) logTextView.movementMethod = ScrollingMovementMethod() viewModel.logText.observe(this, Observer { diff --git a/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteViewModel.kt b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteViewModel.kt index eaaa947..2b0187f 100644 --- a/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteViewModel.kt +++ b/android/app/src/main/java/com/metallic/chiaki/regist/RegistExecuteViewModel.kt @@ -28,7 +28,6 @@ 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 @@ -113,7 +112,7 @@ class RegistExecuteViewModel(val database: AppDatabase): ViewModel() .andThen(dao.insert(registeredHost)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe { _ -> + .subscribe { _ -> /* No, IntelliJ, this "_ ->" IS necessary. */ Log.i("RegistExecute", "Registered Host saved in db") _state.value = State.SUCCESSFUL } diff --git a/android/app/src/main/res/drawable/ic_add_manual.xml b/android/app/src/main/res/drawable/ic_add_manual.xml new file mode 100644 index 0000000..d9ae0a1 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_add_manual.xml @@ -0,0 +1,23 @@ + + + + diff --git a/android/app/src/main/res/layout/activity_add_manual.xml b/android/app/src/main/res/layout/activity_add_manual.xml new file mode 100644 index 0000000..f806d60 --- /dev/null +++ b/android/app/src/main/res/layout/activity_add_manual.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/layout/activity_test_start.xml b/android/app/src/main/res/layout/activity_test_start.xml deleted file mode 100644 index 74bd369..0000000 --- a/android/app/src/main/res/layout/activity_test_start.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/android/app/src/main/res/layout/dropdown_menu_popup_item.xml b/android/app/src/main/res/layout/dropdown_menu_popup_item.xml new file mode 100644 index 0000000..2b175c8 --- /dev/null +++ b/android/app/src/main/res/layout/dropdown_menu_popup_item.xml @@ -0,0 +1,8 @@ + + \ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 913ed5e..5eb0d49 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -35,7 +35,7 @@ PSN Account ID (8 bytes, base64) PIN Register - Please enter a valid host name + Please enter a valid host name Please enter a valid PSN ID Please enter a valid 8-byte Account ID in Base64 Please enter a valid %d-digit PIN @@ -45,6 +45,10 @@ The console with MAC %s has already been registered. Should the previous record be overwritten? Overwrite Cancel + Add Console Manually + Save + Registered Console + Register on first Connection General Stream Registered Consoles diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index e89800c..2ce68e0 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -77,6 +77,14 @@ ?attr/colorPrimaryDark + +