From 012139cb01e713e405289a2a1c366c1ce98d4f20 Mon Sep 17 00:00:00 2001 From: geeksville Date: Wed, 8 Apr 2020 09:53:04 -0700 Subject: [PATCH] remove compose completely and stub out temp broken things --- app/build.gradle | 17 +-- .../ui/fakeandroidview/ComposedView.kt | 104 ------------------ .../java/com/geeksville/mesh/MainActivity.kt | 90 +++++++-------- .../java/com/geeksville/mesh/model/Channel.kt | 2 - .../geeksville/mesh/model/MessagesState.kt | 19 ++-- .../java/com/geeksville/mesh/model/NodeDB.kt | 15 ++- .../java/com/geeksville/mesh/model/UIState.kt | 100 +++++------------ .../com/geeksville/mesh/ui/AndroidImage.kt | 88 --------------- .../com/geeksville/mesh/ui/BTScanScreen.kt | 42 +------ .../java/com/geeksville/mesh/ui/Channel.kt | 26 +---- .../com/geeksville/mesh/ui/ComposeFragment.kt | 56 ---------- .../com/geeksville/mesh/ui/MapFragment.kt | 102 +++++++++-------- .../java/com/geeksville/mesh/ui/MeshApp.kt | 5 +- .../java/com/geeksville/mesh/ui/Messages.kt | 14 +-- .../com/geeksville/mesh/ui/NodeInfoCard.kt | 25 +---- .../java/com/geeksville/mesh/ui/Settings.kt | 11 +- .../java/com/geeksville/mesh/ui/Status.kt | 28 ----- .../com/geeksville/mesh/ui/StyledTextField.kt | 75 ------------- .../java/com/geeksville/mesh/ui/UserIcon.kt | 10 +- .../main/java/com/geeksville/mesh/ui/Users.kt | 10 +- .../java/com/geeksville/mesh/ui/Vectors.kt | 49 --------- build.gradle | 1 - 22 files changed, 161 insertions(+), 728 deletions(-) delete mode 100644 app/src/main/java/androidx/ui/fakeandroidview/ComposedView.kt delete mode 100644 app/src/main/java/com/geeksville/mesh/ui/AndroidImage.kt delete mode 100644 app/src/main/java/com/geeksville/mesh/ui/ComposeFragment.kt delete mode 100644 app/src/main/java/com/geeksville/mesh/ui/Status.kt delete mode 100644 app/src/main/java/com/geeksville/mesh/ui/StyledTextField.kt delete mode 100644 app/src/main/java/com/geeksville/mesh/ui/Vectors.kt diff --git a/app/build.gradle b/app/build.gradle index 3672b1eb0..d35d8cb8f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -29,7 +29,7 @@ android { buildFeatures { // Enables Jetpack Compose for this module - compose true // NOTE, if true main app crashes if you use regular view layout functions + // compose true // NOTE, if true main app crashes if you use regular view layout functions } // Set both the Java and Kotlin compilers to target Java 8. @@ -44,8 +44,8 @@ android { } composeOptions { - kotlinCompilerVersion "1.3.61-dev-withExperimentalGoogleExtensions-20200129" - kotlinCompilerExtensionVersion "$compose_version" + //kotlinCompilerVersion "1.3.61-dev-withExperimentalGoogleExtensions-20200129" + //kotlinCompilerExtensionVersion "$compose_version" } } @@ -99,17 +99,6 @@ dependencies { // mapbox implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:9.0.0' - // You also need to include the following Compose toolkit dependencies. - implementation("androidx.compose:compose-runtime:$compose_version") - implementation("androidx.ui:ui-graphics:$compose_version") - implementation("androidx.ui:ui-layout:$compose_version") - implementation("androidx.ui:ui-material:$compose_version") - implementation("androidx.ui:ui-unit:$compose_version") - implementation("androidx.ui:ui-util:$compose_version") - implementation "androidx.ui:ui-tooling:$compose_version" - androidTestImplementation("androidx.ui:ui-platform:$compose_version") - androidTestImplementation("androidx.ui:ui-test:$compose_version") - // location services implementation 'com.google.android.gms:play-services-location:17.0.0' diff --git a/app/src/main/java/androidx/ui/fakeandroidview/ComposedView.kt b/app/src/main/java/androidx/ui/fakeandroidview/ComposedView.kt deleted file mode 100644 index 0c0e7e4aa..000000000 --- a/app/src/main/java/androidx/ui/fakeandroidview/ComposedView.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package androidx.ui.fakeandroidview - -import android.content.Context -import android.view.LayoutInflater -import android.view.MotionEvent -import android.view.View -import android.view.ViewGroup -import android.view.ViewGroup.LayoutParams.MATCH_PARENT -import androidx.annotation.LayoutRes -import androidx.compose.Composable - -/** - * Composes an Android [View] given a layout resource [resId]. The method handles the inflation - * of the [View] and will call the [postInflationCallback] after this happens. Note that the - * callback will always be invoked on the main thread. - * - * @param resId The id of the layout resource to be inflated. - * @param postInflationCallback The callback to be invoked after the layout is inflated. - */ -@Composable -// TODO(popam): support modifiers here -fun AndroidView(@LayoutRes resId: Int, postInflationCallback: (View) -> Unit = { _ -> }) { - AndroidViewHolder(postInflationCallback = postInflationCallback, resId = resId) -} - - -private class AndroidViewHolder(context: Context) : ViewGroup(context) { - var view: View? = null - set(value) { - if (value != field) { - field = value - removeAllViews() - addView(view) - } - } - - var postInflationCallback: (View) -> Unit = {} - - var resId: Int? = null - set(value) { - if (value != field) { - field = value - val inflater = LayoutInflater.from(context) - val view = inflater.inflate(resId!!, this, false) - this.view = view - postInflationCallback(view) - } - } - - init { - isClickable = true - } - - override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - view?.measure(widthMeasureSpec, heightMeasureSpec) - setMeasuredDimension(view?.measuredWidth ?: 0, view?.measuredHeight ?: 0) - } - - override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { - view?.layout(l, t, r, b) - } - - override fun getLayoutParams(): LayoutParams? { - return view?.layoutParams ?: LayoutParams(MATCH_PARENT, MATCH_PARENT) - } - - /** - * Implement this method to handle touch screen motion events. - * - * - * If this method is used to detect click actions, it is recommended that - * the actions be performed by implementing and calling - * [.performClick]. This will ensure consistent system behavior, - * including: - * - * * obeying click sound preferences - * * dispatching OnClickListener calls - * * handling [ACTION_CLICK][AccessibilityNodeInfo.ACTION_CLICK] when - * accessibility features are enabled - * - * - * @param event The motion event. - * @return True if the event was handled, false otherwise. - */ - override fun onTouchEvent(event: MotionEvent?): Boolean { - return super.onTouchEvent(event) - } -} diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt index f49994221..7f278bb9c 100644 --- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt +++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt @@ -25,9 +25,11 @@ import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.widget.ViewPager2 import com.geeksville.android.Logging import com.geeksville.android.ServiceClient -import com.geeksville.mesh.model.* +import com.geeksville.mesh.model.TextMessage +import com.geeksville.mesh.model.UIViewModel import com.geeksville.mesh.service.* -import com.geeksville.mesh.ui.* +import com.geeksville.mesh.ui.ChannelFragment +import com.geeksville.mesh.ui.MapFragment import com.geeksville.util.Exceptions import com.geeksville.util.exceptionReporter import com.google.android.gms.auth.api.signin.GoogleSignIn @@ -110,6 +112,17 @@ class MainActivity : AppCompatActivity(), Logging, // private val tabIndexes = generateSequence(0) { it + 1 } FIXME, instead do withIndex or zip? to get the ids below, also stop duplicating strings private val tabInfos = arrayOf( + TabInfo( + "Channel", + R.drawable.ic_twotone_contactless_24, + ChannelFragment() + ), + TabInfo( + "Map", + R.drawable.ic_twotone_map_24, + MapFragment() + ) + /* TabInfo( "Messages", R.drawable.ic_twotone_message_24, @@ -119,20 +132,10 @@ class MainActivity : AppCompatActivity(), Logging, "Users", R.drawable.ic_twotone_people_24, ComposeFragment("Users", 3) { UsersContent() }), - TabInfo( - "Channel", - R.drawable.ic_twotone_contactless_24, - ChannelFragment() - ), - TabInfo( - "Map", - R.drawable.ic_twotone_map_24, - MapFragment() - ), TabInfo( "Settings", R.drawable.ic_twotone_settings_applications_24, - BTScanFragment("Settings", 2) { SettingsContent() }) + BTScanFragment("Settings", 2) { SettingsContent() }) */ ) private @@ -211,7 +214,7 @@ class MainActivity : AppCompatActivity(), Logging, private fun sendTestPackets() { exceptionReporter { - val m = UIState.meshService!! + val m = model.meshService!! // Do some test operations val testPayload = "hello world".toByteArray() @@ -232,10 +235,8 @@ class MainActivity : AppCompatActivity(), Logging, override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val prefs = UIState.getPreferences(this) - UIState.ownerName = prefs.getString("owner", "")!! - UIState.meshService = null - UIState.savedInstanceState = savedInstanceState + val prefs = UIViewModel.getPreferences(this) + model.ownerName.value = prefs.getString("owner", "")!! // Ensures Bluetooth is available on the device and it is enabled. If not, // displays a dialog requesting user permission to enable Bluetooth. @@ -301,19 +302,15 @@ class MainActivity : AppCompatActivity(), Logging, val appLinkAction = intent.action val appLinkData: Uri? = intent.data - UIState.requestedChannelUrl = null // assume none - // Were we asked to open one our channel URLs? if (Intent.ACTION_VIEW == appLinkAction) { debug("Asked to open a channel URL - FIXME, ask user if they want to switch to that channel. If so send the config to the radio") - UIState.requestedChannelUrl = appLinkData + val requestedChannelUrl = appLinkData } } override fun onDestroy() { unregisterMeshReceiver() - UIState.meshService = - null // When our activity goes away make sure we don't keep a ptr around to the service super.onDestroy() } @@ -371,40 +368,27 @@ class MainActivity : AppCompatActivity(), Logging, } } - /// Read the config bytes from the radio so we can show them in our GUI, the radio's copy is ground truth - private fun readRadioConfig() { - val bytes = UIState.meshService!!.radioConfig - - val config = MeshProtos.RadioConfig.parseFrom(bytes) - UIState.setRadioConfig(this, config) - - debug("Read config from radio") - } /// Called when we gain/lose a connection to our mesh radio private fun onMeshConnectionChanged(connected: MeshService.ConnectionState) { - UIState.isConnected.value = connected - debug("connchange ${UIState.isConnected.value}") + model.isConnected.value = connected + debug("connchange ${model.isConnected.value}") if (connected == MeshService.ConnectionState.CONNECTED) { - // always get the current radio config when we connect - readRadioConfig() // everytime the radio reconnects, we slam in our current owner data, the radio is smart enough to only broadcast if needed - UIState.setOwner(this) + model.setOwner(this) - val m = UIState.meshService!! + val m = model.meshService!! // Pull down our real node ID - NodeDB.myId.value = m.myId + model.nodeDB.myId.value = m.myId // Update our nodeinfos based on data from the device - NodeDB.nodes.clear() - NodeDB.nodes.putAll( - m.nodes.map - { - it.user?.id!! to it - } - ) + val nodes = m.nodes.map { + it.user?.id!! to it + }.toMap() + + model.nodeDB.nodes.value = nodes } } @@ -435,7 +419,8 @@ class MainActivity : AppCompatActivity(), Logging, // We only care about nodes that have user info info.user?.id?.let { - NodeDB.nodes[it] = info + val newnodes = model.nodeDB.nodes.value!! + Pair(it, info) + model.nodeDB.nodes.value = newnodes } } @@ -456,7 +441,7 @@ class MainActivity : AppCompatActivity(), Logging, payload.toString(utf8) ) - MessagesState.addMessage(msg) + model.messagesState.addMessage(msg) } else -> TODO() } @@ -482,7 +467,6 @@ class MainActivity : AppCompatActivity(), Logging, com.geeksville.mesh.IMeshService.Stub.asInterface(it) }) { override fun onConnected(service: com.geeksville.mesh.IMeshService) { - UIState.meshService = service model.meshService = service // We don't start listening for packets until after we are connected to the service @@ -493,19 +477,19 @@ class MainActivity : AppCompatActivity(), Logging, MeshService.ConnectionState.valueOf(service.connectionState()) onMeshConnectionChanged(connectionState) - debug("connected to mesh service, isConnected=${UIState.isConnected.value}") + debug("connected to mesh service, isConnected=${model.isConnected.value}") } override fun onDisconnected() { unregisterMeshReceiver() - UIState.meshService = null + model.meshService = null } } private fun bindMeshService() { debug("Binding to mesh service!") // we bind using the well known name, to make sure 3rd party apps could also - if (UIState.meshService != null) + if (model.meshService != null) Exceptions.reportError("meshService was supposed to be null, ignoring (but reporting a bug)") MeshService.startService(this)?.let { intent -> @@ -520,7 +504,7 @@ class MainActivity : AppCompatActivity(), Logging, // if we never connected, do nothing debug("Unbinding from mesh service!") mesh.close() - UIState.meshService = null + model.meshService = null } override fun onStop() { diff --git a/app/src/main/java/com/geeksville/mesh/model/Channel.kt b/app/src/main/java/com/geeksville/mesh/model/Channel.kt index ce3e1cc5f..d3c0a6890 100644 --- a/app/src/main/java/com/geeksville/mesh/model/Channel.kt +++ b/app/src/main/java/com/geeksville/mesh/model/Channel.kt @@ -3,7 +3,6 @@ package com.geeksville.mesh.model import android.graphics.Bitmap import android.net.Uri import android.util.Base64 -import androidx.compose.Model import com.geeksville.mesh.MeshProtos import com.google.zxing.BarcodeFormat import com.google.zxing.MultiFormatWriter @@ -11,7 +10,6 @@ import com.journeyapps.barcodescanner.BarcodeEncoder import java.net.MalformedURLException -@Model data class Channel( var name: String, var modemConfig: MeshProtos.ChannelSettings.ModemConfig, diff --git a/app/src/main/java/com/geeksville/mesh/model/MessagesState.kt b/app/src/main/java/com/geeksville/mesh/model/MessagesState.kt index c42c5ce01..3b1f1ede8 100644 --- a/app/src/main/java/com/geeksville/mesh/model/MessagesState.kt +++ b/app/src/main/java/com/geeksville/mesh/model/MessagesState.kt @@ -1,7 +1,7 @@ package com.geeksville.mesh.model import android.os.RemoteException -import androidx.compose.frames.modelListOf +import androidx.lifecycle.MutableLiveData import com.geeksville.android.BuildUtils.isEmulator import com.geeksville.android.Logging import com.geeksville.mesh.MeshProtos @@ -21,8 +21,8 @@ data class TextMessage( ) -object MessagesState : Logging { - private val testTexts = arrayOf( +class MessagesState(private val ui: UIViewModel) : Logging { + private val testTexts = listOf( TextMessage( "+16508765310", "I found the cache" @@ -35,17 +35,20 @@ object MessagesState : Logging { // If the following (unused otherwise) line is commented out, the IDE preview window works. // if left in the preview always renders as empty. - val messages = modelListOf(* if (isEmulator) testTexts else arrayOf()) + val messages = + object : MutableLiveData>(if (isEmulator) testTexts else listOf()) { + + } /// add a message our GUI list of past msgs fun addMessage(m: TextMessage) { - messages.add(m) + messages.value = messages.value!! + m } /// Send a message and added it to our GUI log fun sendMessage(str: String, dest: String? = null) { var error: String? = null - val service = UIState.meshService + val service = ui.meshService if (service != null) try { service.sendData( @@ -59,9 +62,9 @@ object MessagesState : Logging { else error = "Error: No Mesh service" - MessagesState.addMessage( + addMessage( TextMessage( - NodeDB.myId.value, + ui.nodeDB.myId.value!!, str, errorMessage = error ) diff --git a/app/src/main/java/com/geeksville/mesh/model/NodeDB.kt b/app/src/main/java/com/geeksville/mesh/model/NodeDB.kt index 5802cf4b3..6313d5a8f 100644 --- a/app/src/main/java/com/geeksville/mesh/model/NodeDB.kt +++ b/app/src/main/java/com/geeksville/mesh/model/NodeDB.kt @@ -1,13 +1,14 @@ package com.geeksville.mesh.model -import androidx.compose.frames.modelMapOf -import androidx.compose.mutableStateOf +import androidx.lifecycle.MutableLiveData import com.geeksville.android.BuildUtils.isEmulator import com.geeksville.mesh.MeshUser import com.geeksville.mesh.NodeInfo import com.geeksville.mesh.Position -object NodeDB { + +/// NodeDB lives inside the UIViewModel, but it needs a backpointer to reach the service +class NodeDB(private val ui: UIViewModel) { private val testPositions = arrayOf( Position(32.776665, -96.796989, 35), // dallas Position(32.960758, -96.733521, 35), // richardson @@ -43,12 +44,14 @@ object NodeDB { private val seedWithTestNodes = isEmulator /// The unique ID of our node - val myId = mutableStateOf(if (isEmulator) "+16508765309" else "invalid") + val myId = object : MutableLiveData(if (isEmulator) "+16508765309" else "invalid") {} /// A map from nodeid to to nodeinfo val nodes = - modelMapOf(* (if (isEmulator) testNodes else listOf()).map { it.user!!.id to it }.toTypedArray()) + object : + MutableLiveData>(mapOf(*(if (isEmulator) testNodes else listOf()).map { it.user!!.id to it } + .toTypedArray())) {} /// Could be null if we haven't received our node DB yet - val ourNodeInfo get() = nodes[myId.value] + val ourNodeInfo get() = nodes.value!![myId.value] } \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/model/UIState.kt b/app/src/main/java/com/geeksville/mesh/model/UIState.kt index 61797d539..68085e524 100644 --- a/app/src/main/java/com/geeksville/mesh/model/UIState.kt +++ b/app/src/main/java/com/geeksville/mesh/model/UIState.kt @@ -3,11 +3,8 @@ package com.geeksville.mesh.model import android.content.Context import android.content.SharedPreferences import android.net.Uri -import android.os.Bundle import android.os.RemoteException -import androidx.compose.mutableStateOf import androidx.core.content.edit -import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.geeksville.android.BuildUtils.isEmulator @@ -15,7 +12,15 @@ import com.geeksville.android.Logging import com.geeksville.mesh.IMeshService import com.geeksville.mesh.MeshProtos import com.geeksville.mesh.service.MeshService -import com.geeksville.mesh.ui.getInitials + +/// Given a human name, strip out the first letter of the first three words and return that as the initials for +/// that user. +fun getInitials(name: String): String { + val words = name.split(Regex("\\s+")).filter { it.isNotEmpty() }.take(3).map { it.first() } + .joinToString("") + + return words +} class UIViewModel : ViewModel(), Logging { init { @@ -41,32 +46,15 @@ class UIViewModel : ViewModel(), Logging { context.getSharedPreferences("ui-prefs", Context.MODE_PRIVATE) } - override fun onCleared() { - super.onCleared() - debug("ViewModel cleared") - } - var meshService: IMeshService? = null + val nodeDB = NodeDB(this) + val messagesState = MessagesState(this) + /// Are we connected to our radio device val isConnected = - object : LiveData(MeshService.ConnectionState.DISCONNECTED) { - /** - * Called when the number of active observers change to 1 from 0. - * - * - * This callback can be used to know that this LiveData is being used thus should be kept - * up to date. - */ - override fun onActive() { - super.onActive() - - // Get the current radio config from the service - meshService?.let { - debug("Getting connection state from service") - value = MeshService.ConnectionState.valueOf(it.connectionState()) - } - } + object : + MutableLiveData(MeshService.ConnectionState.DISCONNECTED) { } /// various radio settings (including the channel) @@ -89,6 +77,11 @@ class UIViewModel : ViewModel(), Logging { } } + override fun onCleared() { + super.onCleared() + debug("ViewModel cleared") + } + /// Set the radio config (also updates our saved copy in preferences) fun setRadioConfig(context: Context, c: MeshProtos.RadioConfig) { debug("Setting new radio config!") @@ -96,66 +89,28 @@ class UIViewModel : ViewModel(), Logging { radioConfig.value = c getPreferences(context).edit(commit = true) { - this.putString("channel-url", UIState.getChannel()!!.getChannelUrl().toString()) + this.putString("channel-url", getChannel(c)!!.getChannelUrl().toString()) } } -} - -/// FIXME - figure out how to merge this staate with the AppStatus Model -object UIState : Logging { /// Kinda ugly - created in the activity but used from Compose - figure out if there is a cleaner way GIXME // lateinit var googleSignInClient: GoogleSignInClient - var meshService: IMeshService? = null - - /// Are we connected to our radio device - val isConnected = mutableStateOf(MeshService.ConnectionState.DISCONNECTED) - - /// various radio settings (including the channel) - private val radioConfig = mutableStateOf(null) - /// our name in hte radio /// Note, we generate owner initials automatically for now /// our activity will read this from prefs or set it to the empty string - var ownerName: String = "MrInIDE Ownername" + val ownerName = object : MutableLiveData("MrIDE Test") { + } + /// If the app was launched because we received a new channel intent, the Url will be here var requestedChannelUrl: Uri? = null - var savedInstanceState: Bundle? = null - - /** - * Return the current channel info - * FIXME, we should sim channels at the MeshService level if we are running on an emulator, - * for now I just fake it by returning a canned channel. - */ - fun getChannel(): Channel? { - val channel = radioConfig.value?.channelSettings?.let { Channel(it) } - - return if (channel == null && isEmulator) - Channel.emulated - else - channel - } - - fun getPreferences(context: Context): SharedPreferences = - context.getSharedPreferences("ui-prefs", Context.MODE_PRIVATE) - - /// Set the radio config (also updates our saved copy in preferences) - fun setRadioConfig(context: Context, c: MeshProtos.RadioConfig) { - radioConfig.value = c - - getPreferences(context).edit(commit = true) { - this.putString("channel-url", getChannel()!!.getChannelUrl().toString()) - } - } - // clean up all this nasty owner state management FIXME fun setOwner(context: Context, s: String? = null) { if (s != null) { - ownerName = s + ownerName.value = s // note: we allow an empty userstring to be written to prefs getPreferences(context).edit(commit = true) { @@ -164,15 +119,16 @@ object UIState : Logging { } // Note: we are careful to not set a new unique ID - if (ownerName.isNotEmpty()) + if (ownerName.value!!.isNotEmpty()) try { meshService?.setOwner( null, - ownerName, - getInitials(ownerName) + ownerName.value, + getInitials(ownerName.value!!) ) // Note: we use ?. here because we might be running in the emulator } catch (ex: RemoteException) { errormsg("Can't set username on device, is device offline? ${ex.message}") } } } + diff --git a/app/src/main/java/com/geeksville/mesh/ui/AndroidImage.kt b/app/src/main/java/com/geeksville/mesh/ui/AndroidImage.kt deleted file mode 100644 index 85daaf0c8..000000000 --- a/app/src/main/java/com/geeksville/mesh/ui/AndroidImage.kt +++ /dev/null @@ -1,88 +0,0 @@ -package com.geeksville.mesh.ui - -import android.graphics.Bitmap -import androidx.compose.Composable -import androidx.ui.core.DensityAmbient -import androidx.ui.core.DrawModifier -import androidx.ui.core.Modifier -import androidx.ui.core.asModifier -import androidx.ui.foundation.Box -import androidx.ui.graphics.* -import androidx.ui.graphics.colorspace.ColorSpaces -import androidx.ui.graphics.painter.ImagePainter -import androidx.ui.unit.Density -import androidx.ui.unit.PxSize -import androidx.ui.unit.toRect - -/// Stolen from the Compose SimpleImage, replace with their real Image component someday -// TODO(mount, malkov) : remove when RepaintBoundary is a modifier: b/149982905 -// This is class and not val because if b/149985596 -private object ClipModifier : DrawModifier { - override fun draw(density: Density, drawContent: () -> Unit, canvas: Canvas, size: PxSize) { - canvas.save() - canvas.clipRect(size.toRect()) - drawContent() - canvas.restore() - } -} - - -/// Stolen from the Compose SimpleImage, replace with their real Image component someday -@Composable -fun ScaledImage( - image: ImageAsset, - modifier: Modifier = Modifier.None, - tint: Color? = null -) { - with(DensityAmbient.current) { - val imageModifier = ImagePainter(image).asModifier( - scaleFit = ScaleFit.FillMaxDimension, - colorFilter = tint?.let { ColorFilter(it, BlendMode.srcIn) } - ) - Box(modifier + ClipModifier + imageModifier) - } -} - - -/// Borrowed from Compose -class AndroidImage(val bitmap: Bitmap) : ImageAsset { - - /** - * @see Image.width - */ - override val width: Int - get() = bitmap.width - - /** - * @see Image.height - */ - override val height: Int - get() = bitmap.height - - override val config: ImageAssetConfig get() = ImageAssetConfig.Argb8888 - - /** - * @see Image.colorSpace - */ - override val colorSpace: androidx.ui.graphics.colorspace.ColorSpace - get() = ColorSpaces.Srgb - - /** - * @see Image.hasAlpha - */ - override val hasAlpha: Boolean - get() = bitmap.hasAlpha() - - /** - * @see Image.nativeImage - */ - override val nativeImage: NativeImageAsset - get() = bitmap - - /** - * @see - */ - override fun prepareToDraw() { - bitmap.prepareToDraw() - } -} diff --git a/app/src/main/java/com/geeksville/mesh/ui/BTScanScreen.kt b/app/src/main/java/com/geeksville/mesh/ui/BTScanScreen.kt index 1935b7d5e..cc09bf116 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/BTScanScreen.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/BTScanScreen.kt @@ -1,31 +1,7 @@ package com.geeksville.mesh.ui -import android.bluetooth.BluetoothDevice -import android.bluetooth.BluetoothManager -import android.bluetooth.le.* -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter -import android.os.ParcelUuid -import androidx.compose.Composable -import androidx.compose.Model -import androidx.compose.frames.modelMapOf -import androidx.compose.onCommit -import androidx.ui.core.ContextAmbient -import androidx.ui.foundation.Text -import androidx.ui.layout.Column -import androidx.ui.layout.LayoutGravity -import androidx.ui.material.CircularProgressIndicator -import androidx.ui.material.MaterialTheme -import androidx.ui.material.ProvideEmphasis -import androidx.ui.material.RadioGroup -import androidx.ui.tooling.preview.Preview -import com.geeksville.android.Logging -import com.geeksville.mesh.service.RadioInterfaceService -import com.geeksville.util.exceptionReporter - +/* @Model object ScanUIState { var selectedMacAddr: String? = null @@ -171,14 +147,6 @@ fun BTScanScreen() { } else { // val allPaired = bluetoothAdapter?.bondedDevices.orEmpty().map { it.address }.toSet() - /* Only let user select paired devices - val paired = devices.values.filter { allPaired.contains(it.macAddress) } - if (paired.size < devices.size) { - Text( - "Warning: there are nearby Meshtastic devices that are not paired with this phone. Before you can select a device, you will need to pair it in Bluetooth Settings." - ) - } */ - RadioGroup { Column { ScanUIState.devices.values.forEach { @@ -237,10 +205,4 @@ fun BTScanScreen() { } } } - - -@Preview -@Composable -fun btScanScreenPreview() { - BTScanScreen() -} \ No newline at end of file +*/ \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/Channel.kt b/app/src/main/java/com/geeksville/mesh/ui/Channel.kt index da48ac3e8..fa54ddbcb 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/Channel.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/Channel.kt @@ -1,30 +1,16 @@ package com.geeksville.mesh.ui -import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ArrayAdapter import android.widget.AutoCompleteTextView -import androidx.compose.Composable import androidx.fragment.app.activityViewModels import androidx.lifecycle.Observer -import androidx.ui.core.ContextAmbient -import androidx.ui.foundation.Text -import androidx.ui.input.ImeAction -import androidx.ui.layout.* -import androidx.ui.material.MaterialTheme -import androidx.ui.material.OutlinedButton -import androidx.ui.tooling.preview.Preview -import androidx.ui.unit.dp -import com.geeksville.analytics.DataPair -import com.geeksville.android.GeeksvilleApplication import com.geeksville.android.Logging import com.geeksville.mesh.R -import com.geeksville.mesh.model.Channel import com.geeksville.mesh.model.UIViewModel -import com.geeksville.mesh.model.toHumanString import com.google.android.material.textfield.TextInputEditText object ChannelLog : Logging @@ -68,7 +54,7 @@ class ChannelFragment : ScreenFragment("Channel"), Logging { } } - +/* @Composable fun ChannelContent(channel: Channel?) { @@ -165,12 +151,4 @@ fun ChannelContent(channel: Channel?) { } } - -@Preview -@Composable -fun previewChannel() { - // another bug? It seems modaldrawerlayout not yet supported in preview - MaterialTheme(colors = palette) { - ChannelContent(Channel.emulated) - } -} +*/ \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/ComposeFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/ComposeFragment.kt deleted file mode 100644 index dad14ba5a..000000000 --- a/app/src/main/java/com/geeksville/mesh/ui/ComposeFragment.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.geeksville.mesh.ui - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.FrameLayout -import androidx.compose.Composable -import androidx.ui.core.setContent - -fun androidx.fragment.app.Fragment.setComposable( - id: Int, - content: @Composable() () -> Unit -): View? = - context?.let { - FrameLayout(it).apply { - this.isClickable = true - this.id = - id // Compose requires a unique ID for the containing view to make savedInstanceState work - - layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT - ) - setContent(content) - } - } - - -open class ComposeFragment( - screenName: String, - id: Int, - private val content: @Composable() () -> Unit -) : ScreenFragment(screenName) { - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View? = - FrameLayout(context!!).apply { - this.isClickable = true - this.id = - id // Compose requires a unique ID for the containing view to make savedInstanceState work - - layoutParams = ViewGroup.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT - ) - - setContent(content) - } - - /* override fun onStart() { - super.onStart() - (view as ViewGroup).setContent(content) - } */ -} diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index e7ef92a17..5063a6045 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -5,10 +5,12 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.Observer import com.geeksville.android.Logging +import com.geeksville.mesh.NodeInfo import com.geeksville.mesh.R -import com.geeksville.mesh.model.NodeDB -import com.geeksville.mesh.model.UIState +import com.geeksville.mesh.model.UIViewModel import com.mapbox.geojson.Feature import com.mapbox.geojson.FeatureCollection import com.mapbox.geojson.Point @@ -30,6 +32,8 @@ import com.mapbox.mapboxsdk.style.sources.GeoJsonSource class MapFragment : ScreenFragment("Map"), Logging { + private val model: UIViewModel by activityViewModels() + private val nodeSourceId = "node-positions" private val nodeLayerId = "node-layer" private val labelLayerId = "label-layer" @@ -52,56 +56,61 @@ class MapFragment : ScreenFragment("Map"), Logging { textAllowOverlap(true) ) - private fun nodesWithPosition() = NodeDB.nodes.values.filter { it.validPosition != null } - /** - * Using the latest nodedb, generate geojson features - */ - private fun getCurrentNodes(): FeatureCollection { - // Find all nodes with valid locations + private fun onNodesChanged(map: MapboxMap, nodes: Collection) { + val nodesWithPosition = nodes.filter { it.validPosition != null } - val locations = nodesWithPosition().map { node -> - val p = node.position!! - debug("Showing on map: $node") + /** + * Using the latest nodedb, generate geojson features + */ + fun getCurrentNodes(): FeatureCollection { + // Find all nodes with valid locations - val f = Feature.fromGeometry( - Point.fromLngLat( - p.longitude, - p.latitude + val locations = nodesWithPosition.map { node -> + val p = node.position!! + debug("Showing on map: $node") + + val f = Feature.fromGeometry( + Point.fromLngLat( + p.longitude, + p.latitude + ) ) - ) - node.user?.let { - f.addStringProperty("name", it.longName) + node.user?.let { + f.addStringProperty("name", it.longName) + } + f } - f + + return FeatureCollection.fromFeatures(locations) } - return FeatureCollection.fromFeatures(locations) - } + fun zoomToNodes(map: MapboxMap) { + if (nodesWithPosition.isNotEmpty()) { + val update = if (nodesWithPosition.size >= 2) { + // Multiple nodes, make them all fit on the map view + val bounds = LatLngBounds.Builder() - private fun zoomToNodes(map: MapboxMap) { - val nodes = nodesWithPosition() - if (nodes.isNotEmpty()) { - val update = if (nodes.size >= 2) { - // Multiple nodes, make them all fit on the map view - val bounds = LatLngBounds.Builder() + // Add all positions + bounds.includes(nodes.map { it.position!! } + .map { LatLng(it.latitude, it.longitude) }) - // Add all positions - bounds.includes(nodes.map { it.position!! } - .map { LatLng(it.latitude, it.longitude) }) + CameraUpdateFactory.newLatLngBounds(bounds.build(), 150) + } else { + // Only one node, just zoom in on it + val it = nodesWithPosition[0].position!! - CameraUpdateFactory.newLatLngBounds(bounds.build(), 150) - } else { - // Only one node, just zoom in on it - val it = nodes[0].position!! - - val cameraPos = CameraPosition.Builder().target( - LatLng(it.latitude, it.longitude) - ).zoom(9.0).build() - CameraUpdateFactory.newCameraPosition(cameraPos) + val cameraPos = CameraPosition.Builder().target( + LatLng(it.latitude, it.longitude) + ).zoom(9.0).build() + CameraUpdateFactory.newCameraPosition(cameraPos) + } + map.animateCamera(update, 1000) } - map.animateCamera(update, 1000) } + + nodePositions.setGeoJson(getCurrentNodes()) // Update node positions + zoomToNodes(map) } override fun onCreateView( @@ -115,12 +124,12 @@ class MapFragment : ScreenFragment("Map"), Logging { super.onViewCreated(view, savedInstanceState) mapView = view.findViewById(R.id.mapView) - mapView.onCreate(UIState.savedInstanceState) + mapView.onCreate(savedInstanceState) mapView.getMapAsync { map -> // val markerIcon = BitmapFactory.decodeResource(context.resources, R.drawable.ic_twotone_person_pin_24) - val markerIcon = activity!!.getDrawable(R.drawable.ic_twotone_person_pin_24)!! + val markerIcon = requireActivity().getDrawable(R.drawable.ic_twotone_person_pin_24)!! map.setStyle(Style.OUTDOORS) { style -> style.addSource(nodePositions) @@ -129,6 +138,10 @@ class MapFragment : ScreenFragment("Map"), Logging { style.addLayer(labelLayer) } + model.nodeDB.nodes.observe(viewLifecycleOwner, Observer { nodes -> + onNodesChanged(map, nodes.values) + }) + //map.uiSettings.isScrollGesturesEnabled = true //map.uiSettings.isZoomGesturesEnabled = true } @@ -152,11 +165,6 @@ class MapFragment : ScreenFragment("Map"), Logging { override fun onResume() { super.onResume() mapView.onResume() - - mapView.getMapAsync { map -> - nodePositions.setGeoJson(getCurrentNodes()) // Update node positions - zoomToNodes(map) - } } override fun onDestroy() { diff --git a/app/src/main/java/com/geeksville/mesh/ui/MeshApp.kt b/app/src/main/java/com/geeksville/mesh/ui/MeshApp.kt index 8958d63ba..c835b2aa1 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MeshApp.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MeshApp.kt @@ -1,14 +1,13 @@ package com.geeksville.mesh.ui -import androidx.ui.material.lightColorPalette import com.geeksville.android.Logging object UILog : Logging - +/* val palette = lightColorPalette() // darkColorPalette() -/* + @Composable fun MeshApp() { val (drawerState, onDrawerStateChange) = state { DrawerState.Closed } diff --git a/app/src/main/java/com/geeksville/mesh/ui/Messages.kt b/app/src/main/java/com/geeksville/mesh/ui/Messages.kt index ba71fa362..bcd254af0 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/Messages.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/Messages.kt @@ -1,5 +1,6 @@ package com.geeksville.mesh.ui +/* import androidx.compose.Composable import androidx.compose.state import androidx.ui.core.Modifier @@ -31,9 +32,7 @@ val TimestampEmphasis = object : Emphasis { } -/** - * A pretty version the text, with user icon to the left, name and time of arrival (copy slack look and feel) - */ +/// A pretty version the text, with user icon to the left, name and time of arrival (copy slack look and feel) @Composable fun MessageCard(msg: TextMessage, modifier: Modifier = Modifier.None) { Row(modifier = modifier) { @@ -112,11 +111,4 @@ fun MessagesContent() { } -@Preview -@Composable -fun previewMessagesView() { - // another bug? It seems modaldrawerlayout not yet supported in preview - MaterialTheme(colors = palette) { - MessagesContent() - } -} +*/ \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/NodeInfoCard.kt b/app/src/main/java/com/geeksville/mesh/ui/NodeInfoCard.kt index 132b5f732..1b0176e41 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/NodeInfoCard.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/NodeInfoCard.kt @@ -1,5 +1,6 @@ package com.geeksville.mesh.ui +/* import androidx.compose.Composable import androidx.ui.foundation.Text import androidx.ui.layout.* @@ -13,22 +14,7 @@ import com.geeksville.mesh.model.NodeDB import androidx.ui.core.Modifier as Modifier1 -/* -@Composable -fun NodeIcon(modifier: Modifier1 = Modifier1.None, node: NodeInfo) { - Column { - Container(modifier = modifier + LayoutSize(40.dp, 40.dp)) { - VectorImage(id = if (node.user?.shortName != null) R.drawable.person else R.drawable.help) - } - // Show our shortname if possible - /* node.user?.shortName?.let { - Text(it) - } */ - - } -} - */ @Composable fun CompassHeading(modifier: Modifier1 = Modifier1.None, node: NodeInfo) { @@ -81,11 +67,4 @@ fun NodeInfoCard(node: NodeInfo) { } } -@Preview -@Composable -fun nodeInfoPreview() { - Column { - NodeInfoCard(NodeDB.testNodes[0]) - NodeInfoCard(NodeDB.testNodeNoPosition) - } -} \ No newline at end of file +*/ \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/Settings.kt b/app/src/main/java/com/geeksville/mesh/ui/Settings.kt index f8c1da885..576445cb8 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/Settings.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/Settings.kt @@ -1,5 +1,6 @@ package com.geeksville.mesh.ui +/* import androidx.compose.Composable import androidx.compose.state import androidx.ui.core.ContextAmbient @@ -68,12 +69,4 @@ fun SettingsContent() { } } - -@Preview -@Composable -fun previewSettings() { - // another bug? It seems modaldrawerlayout not yet supported in preview - MaterialTheme(colors = palette) { - SettingsContent() - } -} +*/ \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/Status.kt b/app/src/main/java/com/geeksville/mesh/ui/Status.kt deleted file mode 100644 index c20355c3a..000000000 --- a/app/src/main/java/com/geeksville/mesh/ui/Status.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.geeksville.mesh.ui - -/* -data class ScreenInfo(val icon: Int, val label: String) - -// defines the screens we have in the app -object Screen { - val settings = ScreenInfo(R.drawable.ic_twotone_settings_applications_24, "Settings") - val channel = ScreenInfo(R.drawable.ic_twotone_contactless_24, "Channel") - val users = ScreenInfo(R.drawable.ic_twotone_people_24, "Users") - val messages = ScreenInfo(R.drawable.ic_twotone_message_24, "Messages") - val map = ScreenInfo(R.drawable.ic_twotone_map_24, "Map") -} - - -@Model -object AppStatus { - var currentScreen: ScreenInfo = Screen.messages -} - - -/** - * Temporary solution pending navigation support. - */ -fun navigateTo(destination: ScreenInfo) { - AppStatus.currentScreen = destination -} -*/ \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/StyledTextField.kt b/app/src/main/java/com/geeksville/mesh/ui/StyledTextField.kt deleted file mode 100644 index b3c3b4fb6..000000000 --- a/app/src/main/java/com/geeksville/mesh/ui/StyledTextField.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.geeksville.mesh.ui - -import androidx.compose.Composable -import androidx.compose.state -import androidx.ui.core.Modifier -import androidx.ui.foundation.TextField -import androidx.ui.foundation.shape.corner.RoundedCornerShape -import androidx.ui.graphics.Color -import androidx.ui.input.ImeAction -import androidx.ui.input.KeyboardType -import androidx.ui.input.VisualTransformation -import androidx.ui.layout.LayoutPadding -import androidx.ui.material.Emphasis -import androidx.ui.material.MaterialTheme -import androidx.ui.material.ProvideEmphasis -import androidx.ui.material.Surface -import androidx.ui.text.TextStyle -import androidx.ui.unit.dp - - -val HintEmphasis = object : Emphasis { - override fun emphasize(color: Color) = color.copy(alpha = 0.05f) -} - - -/// A text field that visually conveys that it is editable - FIXME, once Compose has material -/// design text fields use that instead. -@Composable -fun StyledTextField( - value: String, - modifier: Modifier = Modifier.None, - onValueChange: (String) -> Unit = {}, - textStyle: TextStyle = TextStyle.Default, - keyboardType: KeyboardType = KeyboardType.Text, - imeAction: ImeAction = ImeAction.Unspecified, - onFocus: () -> Unit = {}, - onBlur: () -> Unit = {}, - focusIdentifier: String? = null, - onImeActionPerformed: (ImeAction) -> Unit = {}, - visualTransformation: VisualTransformation? = null, - hintText: String = "" -) { - val backgroundColor = palette.secondary.copy(alpha = 0.12f) - Surface( - modifier = LayoutPadding(8.dp), - color = backgroundColor, - shape = RoundedCornerShape(4.dp) - ) { - val showingHint = state { value.isEmpty() } - val level = if (showingHint.value) HintEmphasis else MaterialTheme.emphasisLevels.medium - - ProvideEmphasis(level) { - TextField( - value.ifEmpty { if (showingHint.value) hintText else "" }, - modifier + LayoutPadding(4.dp), - onValueChange, - textStyle, - keyboardType, - imeAction, - { - showingHint.value = false // Stop showing the hint now - onFocus() - }, - { - // if the string is empty again, return to the hint text - showingHint.value = value.isEmpty() - onBlur() - }, - focusIdentifier, - onImeActionPerformed, - visualTransformation - ) - } - } -} diff --git a/app/src/main/java/com/geeksville/mesh/ui/UserIcon.kt b/app/src/main/java/com/geeksville/mesh/ui/UserIcon.kt index ceee5d748..292af382f 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/UserIcon.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/UserIcon.kt @@ -1,5 +1,6 @@ package com.geeksville.mesh.ui +/* import androidx.compose.Composable import androidx.ui.core.Modifier import androidx.ui.foundation.Text @@ -34,11 +35,4 @@ fun UserIcon(user: NodeInfo? = null, modifier: Modifier = Modifier.None) { } } -@Preview -@Composable -fun previewUserIcon() { - // another bug? It seems modaldrawerlayout not yet supported in preview - MaterialTheme(colors = palette) { - UserIcon(NodeDB.testNodes[1]) - } -} +*/ \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/Users.kt b/app/src/main/java/com/geeksville/mesh/ui/Users.kt index 10abb0899..a02b18036 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/Users.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/Users.kt @@ -1,5 +1,6 @@ package com.geeksville.mesh.ui +/* import androidx.compose.Composable import androidx.ui.core.ContextAmbient import androidx.ui.foundation.Text @@ -16,14 +17,7 @@ import com.geeksville.mesh.service.RadioInterfaceService import com.geeksville.mesh.service.SoftwareUpdateService -/// Given a human name, strip out the first letter of the first three words and return that as the initials for -/// that user. -fun getInitials(name: String): String { - val words = name.split(Regex("\\s+")).filter { it.isNotEmpty() }.take(3).map { it.first() } - .joinToString("") - return words -} @Composable fun UsersContent() { @@ -88,3 +82,5 @@ fun UsersContent() { } */ } } + +*/ \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/Vectors.kt b/app/src/main/java/com/geeksville/mesh/ui/Vectors.kt deleted file mode 100644 index 9aa4fb313..000000000 --- a/app/src/main/java/com/geeksville/mesh/ui/Vectors.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.geeksville.mesh.ui - -import androidx.annotation.DrawableRes -import androidx.compose.Composable -import androidx.ui.core.Modifier -import androidx.ui.foundation.Icon -import androidx.ui.graphics.Color -import androidx.ui.graphics.vector.drawVector -import androidx.ui.layout.Container -import androidx.ui.layout.LayoutSize -import androidx.ui.material.IconButton -import androidx.ui.res.vectorResource - - -@Composable -fun VectorImageButton(@DrawableRes id: Int, onClick: () -> Unit) { - //Ripple(bounded = false) { - IconButton(onClick = onClick) { - Icon(vectorResource(id) /* , modifier = LayoutSize(40.dp, 40.dp) */) - } - //} -} - -/* fun AppBarIcon(icon: Image, onClick: () -> Unit) { - Container(width = ActionIconDiameter, height = ActionIconDiameter) { - Ripple(bounded = false) { - Clickable(onClick = onClick) { - SimpleImage(icon) - } - } - } -} */ - -@Composable -fun VectorImage( - modifier: Modifier = Modifier.None, @DrawableRes id: Int, - tint: Color = Color.Transparent -) { - val vector = vectorResource(id) - // WithDensity { - Container( - modifier = modifier + LayoutSize( - vector.defaultWidth, - vector.defaultHeight - ) + drawVector(vector, tint) - ) { - } - // } -} diff --git a/build.gradle b/build.gradle index 0ccd6f27d..5fd2e8273 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,6 @@ buildscript { ext.kotlin_version = '1.3.61' - ext.compose_version = '0.1.0-dev08' ext.coroutines_version = "1.3.5" repositories {