Disable Manual Console on Android

This commit is contained in:
Florian Märkl 2019-10-03 21:51:18 +02:00
commit 2dc2fcdd56
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
17 changed files with 378 additions and 47 deletions

View file

@ -55,9 +55,10 @@ dependencies {
implementation 'androidx.core:core-ktx:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.recyclerview:recyclerview:1.0.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.google.android.material:material:1.1.0-alpha10'
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0"
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0'
implementation 'androidx.lifecycle:lifecycle-reactivestreams:2.1.0'
implementation "io.reactivex.rxjava2:rxjava:2.2.12"
implementation "io.reactivex.rxjava2:rxkotlin:2.4.0"
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'

View file

@ -22,14 +22,21 @@ import com.metallic.chiaki.lib.DiscoveryHost
sealed class DisplayHost
{
abstract val registeredHost: RegisteredHost?
abstract val host: String
}
class DiscoveredDisplayServer(
class DiscoveredDisplayHost(
override val registeredHost: RegisteredHost?,
val discoveredHost: DiscoveryHost
): DisplayHost()
{
override val host get() = discoveredHost.hostAddr ?: ""
}
class ManualDisplayServer(
class ManualDisplayHost(
override val registeredHost: RegisteredHost?,
val manualHost: ManualHost
): DisplayHost()
): DisplayHost()
{
override val host get() = manualHost.host
}

View file

@ -0,0 +1,23 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.metallic.chiaki.common.ext
import androidx.lifecycle.LiveDataReactiveStreams
import org.reactivestreams.Publisher
fun <T> Publisher<T>.toLiveData() = LiveDataReactiveStreams.fromPublisher(this)

View file

@ -0,0 +1,28 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.metallic.chiaki.common.ext
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
fun ViewGroup.inflate(@LayoutRes layoutRes: Int, attachToRoot: Boolean = false): View
{
return LayoutInflater.from(context).inflate(layoutRes, this, attachToRoot)
}

View file

@ -0,0 +1,11 @@
package com.metallic.chiaki.common.ext
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
inline fun <T: ViewModel> viewModelFactory(crossinline f: () -> T) =
object : ViewModelProvider.Factory
{
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(aClass: Class<T>): T = f() as T
}

View file

@ -181,14 +181,14 @@ class Session(connectInfo: ConnectInfo)
data class DiscoveryHost(
val state: State,
val hostRequestPort: UShort,
val host_addr: String?,
val system_version: String?,
val device_discovery_protocol_version: String?,
val host_name: String?,
val host_type: String?,
val host_id: String?,
val running_app_titleid: String?,
val running_app_name: String?)
val hostAddr: String?,
val systemVersion: String?,
val deviceDiscoveryProtocolVersion: String?,
val hostName: String?,
val hostType: String?,
val hostId: String?,
val runningAppTitleid: String?,
val runningAppName: String?)
{
enum class State
{

View file

@ -0,0 +1,51 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.metallic.chiaki.main
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.metallic.chiaki.R
import com.metallic.chiaki.common.DisplayHost
import com.metallic.chiaki.common.ext.inflate
import kotlinx.android.synthetic.main.item_display_host.view.*
class DisplayHostRecyclerViewAdapter: RecyclerView.Adapter<DisplayHostRecyclerViewAdapter.ViewHolder>()
{
var hosts: List<DisplayHost> = listOf()
set(value)
{
field = value
notifyDataSetChanged()
}
class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)
= ViewHolder(parent.inflate(R.layout.item_display_host))
override fun getItemCount() = hosts.count()
override fun onBindViewHolder(holder: ViewHolder, position: Int)
{
val host = hosts[position]
holder.itemView.also {
it.hostTextView.text = host.host
}
}
}

View file

@ -21,16 +21,14 @@ import android.app.ActivityOptions
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProviders
import androidx.recyclerview.widget.LinearLayoutManager
import com.metallic.chiaki.R
import com.metallic.chiaki.TestStartActivity
import com.metallic.chiaki.common.ManualHost
import com.metallic.chiaki.common.getDatabase
import io.reactivex.Completable
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import com.metallic.chiaki.common.ext.viewModelFactory
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity()
@ -50,18 +48,14 @@ class MainActivity : AppCompatActivity()
}
}
/*val db = getDatabase(this)
Completable.mergeArray(
db.manualHostDao().insert(ManualHost(host = "test", registeredHost = null)),
db.manualHostDao().insert(ManualHost(host = "adsgsdfgdsfg", registeredHost = null)),
db.manualHostDao().insert(ManualHost(host = "sdfgsdfg", registeredHost = null))
).andThen(db.manualHostDao().getAll())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
Log.i("MainActivity", "got $it")
}
.also { disposable.add(it) }*/
val viewModel = ViewModelProviders
.of(this, viewModelFactory { MainViewModel(getDatabase(this)) })
.get(MainViewModel::class.java)
val recyclerViewAdapter = DisplayHostRecyclerViewAdapter()
hostsRecyclerView.adapter = recyclerViewAdapter
hostsRecyclerView.layoutManager = LinearLayoutManager(this)
viewModel.displayHosts.observe(this, Observer { recyclerViewAdapter.hosts = it })
}
override fun onDestroy()

View file

@ -18,8 +18,19 @@
package com.metallic.chiaki.main
import androidx.lifecycle.ViewModel
import com.metallic.chiaki.common.AppDatabase
import com.metallic.chiaki.common.ManualDisplayHost
import com.metallic.chiaki.common.ext.toLiveData
class MainViewModel: ViewModel()
class MainViewModel(val database: AppDatabase): ViewModel()
{
val displayHosts by lazy {
database.manualHostDao().getAll()
.map {
it.map { manualHost ->
ManualDisplayHost(null, manualHost)
}
}
.toLiveData()
}
}

View file

@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="86dp"
android:viewportWidth="135.46666"
android:viewportHeight="22.754168">
<path
android:pathData="m13.537,0 l-5.607,9.425l121.929,0l5.607,-9.425zM5.606,13.33 L0,22.754l121.929,0l5.606,-9.424z"
android:strokeAlpha="1"
android:strokeWidth="12.74962807"
android:fillColor="?android:attr/textColorPrimary"
android:strokeColor="#00000000"
android:fillAlpha="1"/>
</vector>

View file

@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="86dp"
android:viewportWidth="135.46666"
android:viewportHeight="22.754168">
<path
android:pathData="m13.537,0 l-5.607,9.425l121.929,0l5.607,-9.425zM5.606,13.33 L0,22.754l121.929,0l5.606,-9.424z"
android:strokeAlpha="1"
android:strokeWidth="12.74962807"
android:fillColor="#000000"
android:strokeColor="#00000000"
android:fillAlpha="1"/>
<path
android:pathData="m7.93,9.425 l-2.324,3.906l121.929,0l2.324,-3.906z"
android:strokeAlpha="1"
android:strokeWidth="12.74962807"
android:fillColor="#ffae2f"
android:strokeColor="#00000000"
android:fillAlpha="1"/>
</vector>

View file

@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="512dp"
android:height="86dp"
android:viewportWidth="135.46666"
android:viewportHeight="22.754168">
<path
android:pathData="m13.537,0 l-5.607,9.425l121.929,0l5.607,-9.425zM5.606,13.33 L0,22.754l121.929,0l5.606,-9.424z"
android:strokeAlpha="1"
android:strokeWidth="12.74962807"
android:fillColor="#000000"
android:strokeColor="#00000000"
android:fillAlpha="1"/>
<path
android:pathData="m7.93,9.425 l-2.324,3.906l121.929,0l2.324,-3.906z"
android:strokeAlpha="1"
android:strokeWidth="12.74962807"
android:fillColor="#ffae2f"
android:strokeColor="#00000000"
android:fillAlpha="1"/>
</vector>

View file

@ -1,15 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".main.MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/consolesRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/addButton"
@ -17,7 +11,36 @@
android:layout_height="wrap_content"
android:src="@drawable/ic_add"
android:layout_margin="16dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
android:layout_gravity="bottom|end" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/hostsRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="8dp"
android:clipToPadding="false"
android:clipChildren="false"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
<com.google.android.material.appbar.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">
<com.google.android.material.appbar.MaterialToolbar
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:background="?attr/colorPrimarySurface"
app:layout_scrollFlags="scroll|enterAlways">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fontFamily="sans-serif-condensed"
android:text="@string/main_title"
android:textColor="?attr/colorOnPrimary"
android:textSize="20dp" />
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="250dp"
app:cardCornerRadius="4dp"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="0dp"
android:elevation="8dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/hostTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-condensed-medium"
app:layout_constraintTop_toTopOf="parent"
tools:text="Host"
android:textSize="16sp"
android:gravity="center"
android:textColor="?attr/colorOnSurface"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/ic_console"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginLeft="32dp"
android:layout_marginRight="32dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>

View file

@ -1,5 +1,6 @@
<resources>
<string name="app_name">Chiaki</string>
<string name="main_title">Chiaki 千秋</string>
<string name="alert_message_session_quit">Session has quit: %s</string>
<string name="alert_message_session_create_error">Failed to create Session: %s</string>
<string name="alert_message_login_pin_request">Login PIN:</string>

View file

@ -1,8 +1,13 @@
<resources>
<style name="AppTheme" parent="Theme.AppCompat.DayNight.DarkActionBar">
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primary_dark</item>
<item name="colorAccent">@color/accent</item>
<item name="colorOnPrimary">#ffffff</item>
<item name="colorSecondary">@color/accent</item>
<item name="colorOnSecondary">#000000</item>
<item name="android:statusBarColor">?attr/colorPrimarySurface</item>
<item name="android:navigationBarColor">?attr/colorPrimarySurface</item>
<item name="android:windowActivityTransitions">true</item>
</style>

74
assets/console.svg Normal file
View file

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="86"
viewBox="0 0 135.46666 22.754167"
version="1.1"
id="svg965"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
sodipodi:docname="console.svg">
<defs
id="defs959" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
inkscape:cx="300.0445"
inkscape:cy="77.810757"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1918"
inkscape:window-height="1048"
inkscape:window-x="0"
inkscape:window-y="15"
inkscape:window-maximized="1" />
<metadata
id="metadata962">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-274.24582)">
<g
id="g956"
transform="matrix(1.3273345,0,0,1.3071608,-53.478391,126.49438)">
<path
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:12.74962807;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 50.489042,113.03234 -4.224384,7.21001 h 91.860192 l 4.22439,-7.21001 z m -5.975155,10.19787 -4.223824,7.20945 h 91.860187 l 4.22384,-7.20945 z"
id="path950"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccccc" />
<path
sodipodi:nodetypes="ccccc"
inkscape:connector-curvature="0"
id="path952"
d="m 46.264658,120.24235 -1.750771,2.98786 h 91.860193 l 1.75078,-2.98786 z"
style="fill:#ffae2f;fill-opacity:1;stroke:none;stroke-width:12.74962807;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB