diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt
index 5653eccfc..2dbd0c17f 100644
--- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt
+++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt
@@ -12,18 +12,16 @@ import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
-import android.view.*
-import android.widget.FrameLayout
+import android.view.Menu
+import android.view.MenuItem
+import android.view.MotionEvent
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
-import androidx.compose.Composable
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
-import androidx.ui.core.setContent
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
-import com.geeksville.android.GeeksvilleApplication
import com.geeksville.android.Logging
import com.geeksville.android.ServiceClient
import com.geeksville.mesh.model.MessagesState
@@ -92,50 +90,6 @@ eventually:
val utf8 = Charset.forName("UTF-8")
-fun androidx.fragment.app.Fragment.setComposable(
- id: Int,
- content: @Composable() () -> Unit
-): View? =
- context?.let {
- FrameLayout(it).apply {
- 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)
- }
- }
-
-/**
- * A fragment that represents a current 'screen' in our app.
- *
- * Useful for tracking analytics
- */
-open class ScreenFragment(private val screenName: String) : Fragment() {
- override fun onResume() {
- super.onResume()
- GeeksvilleApplication.analytics.sendScreenView(screenName)
- }
-
- override fun onPause() {
- GeeksvilleApplication.analytics.endScreenView()
- super.onPause()
- }
-}
-
-class ComposeFragment(screenName: String, id: Int, private val content: @Composable() () -> Unit) :
- ScreenFragment(screenName),
- Logging {
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?,
- savedInstanceState: Bundle?
- ): View? =
- setComposable(id, content)
-}
-
class MainActivity : AppCompatActivity(), Logging,
ActivityCompat.OnRequestPermissionsResultCallback {
@@ -195,7 +149,8 @@ class MainActivity : AppCompatActivity(), Logging,
TabInfo(
"Map",
R.drawable.ic_twotone_map_24,
- ComposeFragment("Map", 5) { MapContent() })
+ MapFragment()
+ )
)
private
diff --git a/app/src/main/java/com/geeksville/mesh/ui/ComposeFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/ComposeFragment.kt
new file mode 100644
index 000000000..1986d4b08
--- /dev/null
+++ b/app/src/main/java/com/geeksville/mesh/ui/ComposeFragment.kt
@@ -0,0 +1,38 @@
+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
+import com.geeksville.android.Logging
+
+fun androidx.fragment.app.Fragment.setComposable(
+ id: Int,
+ content: @Composable() () -> Unit
+): View? =
+ context?.let {
+ FrameLayout(it).apply {
+ 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)
+ }
+ }
+
+
+class ComposeFragment(screenName: String, id: Int, private val content: @Composable() () -> Unit) :
+ ScreenFragment(screenName),
+ Logging {
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? =
+ setComposable(id, content)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/geeksville/mesh/ui/Map.kt b/app/src/main/java/com/geeksville/mesh/ui/Map.kt
index 08b4e6f57..3c5934fd1 100644
--- a/app/src/main/java/com/geeksville/mesh/ui/Map.kt
+++ b/app/src/main/java/com/geeksville/mesh/ui/Map.kt
@@ -1,15 +1,10 @@
package com.geeksville.mesh.ui
-import android.app.Activity
-import android.app.Application
import android.graphics.Color
import android.os.Bundle
-import androidx.compose.Composable
-import androidx.compose.onCommit
-import androidx.ui.core.ContextAmbient
-import androidx.ui.fakeandroidview.AndroidView
-import androidx.ui.material.MaterialTheme
-import androidx.ui.tooling.preview.Preview
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
import com.geeksville.android.Logging
import com.geeksville.mesh.R
import com.geeksville.mesh.model.NodeDB
@@ -32,114 +27,65 @@ import com.mapbox.mapboxsdk.style.layers.SymbolLayer
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
-object mapLog : Logging
+class MapFragment : ScreenFragment("Map"), Logging {
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? = inflater.inflate(R.layout.map_view, container, false)
+ lateinit var mapView: MapView
-/**
- * mapbox requires this, until compose has a nicer way of doing it, do it here
- */
-private val mapLifecycleCallbacks = object : Application.ActivityLifecycleCallbacks {
- var view: MapView? = null
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
- override fun onActivityPaused(activity: Activity) {
- view?.onPause()
- }
+ mapView = view.findViewById(R.id.mapView)
+ mapView.onCreate(UIState.savedInstanceState)
- override fun onActivityStarted(activity: Activity) {
- view?.onStart()
- }
+ mapView.getMapAsync { map ->
- override fun onActivityDestroyed(activity: Activity) {
- view?.onDestroy()
- }
+ // Find all nodes with valid locations
+ val nodesWithPosition = NodeDB.nodes.values.filter { it.validPosition != null }
+ val locations = nodesWithPosition.map { node ->
+ val p = node.position!!
+ debug("Showing on map: $node")
- override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
- view?.onSaveInstanceState(outState)
- }
+ val f = Feature.fromGeometry(
+ Point.fromLngLat(
+ p.longitude,
+ p.latitude
+ )
+ )
+ node.user?.let {
+ f.addStringProperty("name", it.longName)
+ }
+ f
+ }
+ val nodeSourceId = "node-positions"
+ val nodeLayerId = "node-layer"
+ val labelLayerId = "label-layer"
+ val markerImageId = "my-marker-image"
+ val nodePositions =
+ GeoJsonSource(nodeSourceId, FeatureCollection.fromFeatures(locations))
- override fun onActivityStopped(activity: Activity) {
- view?.onStop()
- }
+ // val markerIcon = BitmapFactory.decodeResource(context.resources, R.drawable.ic_twotone_person_pin_24)
+ val markerIcon = activity!!.getDrawable(R.drawable.ic_twotone_person_pin_24)!!
- /**
- * Called when the Activity calls [super.onCreate()][Activity.onCreate].
- */
- override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
- }
-
- override fun onActivityResumed(activity: Activity) {
- view?.onResume()
- }
-}
-
-
-@Composable
-fun MapContent() {
- val context = ContextAmbient.current
-
- // FIXME - remove onCommit
- onCommit() {
- onDispose {
- // We no longer care about activity lifecycle
- (context.applicationContext as Application).unregisterActivityLifecycleCallbacks(
- mapLifecycleCallbacks
+ val nodeLayer = SymbolLayer(nodeLayerId, nodeSourceId).withProperties(
+ iconImage(markerImageId),
+ iconAnchor(Property.ICON_ANCHOR_BOTTOM),
+ iconAllowOverlap(true)
)
- mapLifecycleCallbacks.view = null
- }
- }
- // Find all nodes with valid locations
- val nodesWithPosition = NodeDB.nodes.values.filter { it.validPosition != null }
- val locations = nodesWithPosition.map { node ->
- val p = node.position!!
- mapLog.debug("Showing on map: $node")
-
- val f = Feature.fromGeometry(
- Point.fromLngLat(
- p.longitude,
- p.latitude
+ val labelLayer = SymbolLayer(labelLayerId, nodeSourceId).withProperties(
+ textField(Expression.get("name")),
+ textSize(12f),
+ textColor(Color.RED),
+ textVariableAnchor(arrayOf(TEXT_ANCHOR_TOP)),
+ textJustify(TEXT_JUSTIFY_AUTO),
+ textAllowOverlap(true)
)
- )
- node.user?.let {
- f.addStringProperty("name", it.longName)
- }
- f
- }
- val nodeSourceId = "node-positions"
- val nodeLayerId = "node-layer"
- val labelLayerId = "label-layer"
- val markerImageId = "my-marker-image"
- val nodePositions =
- GeoJsonSource(nodeSourceId, FeatureCollection.fromFeatures(locations))
- // val markerIcon = BitmapFactory.decodeResource(context.resources, R.drawable.ic_twotone_person_pin_24)
- val markerIcon = context.getDrawable(R.drawable.ic_twotone_person_pin_24)!!
-
- val nodeLayer = SymbolLayer(nodeLayerId, nodeSourceId).withProperties(
- iconImage(markerImageId),
- iconAnchor(Property.ICON_ANCHOR_BOTTOM),
- iconAllowOverlap(true)
- )
-
- val labelLayer = SymbolLayer(labelLayerId, nodeSourceId).withProperties(
- textField(Expression.get("name")),
- textSize(12f),
- textColor(Color.RED),
- textVariableAnchor(arrayOf(TEXT_ANCHOR_TOP)),
- textJustify(TEXT_JUSTIFY_AUTO),
- textAllowOverlap(true)
- )
-
- AndroidView(R.layout.map_view) { view ->
- view as MapView
- view.onCreate(UIState.savedInstanceState)
-
- mapLifecycleCallbacks.view = view
- (context.applicationContext as Application).registerActivityLifecycleCallbacks(
- mapLifecycleCallbacks
- )
-
- view.getMapAsync { map ->
map.setStyle(Style.OUTDOORS) { style ->
style.addSource(nodePositions)
style.addImage(markerImageId, markerIcon)
@@ -173,14 +119,38 @@ fun MapContent() {
}
}
}
-}
+ override fun onPause() {
+ mapView.onPause()
+ super.onPause()
+ }
-@Preview
-@Composable
-fun previewMap() {
- // another bug? It seems modaldrawerlayout not yet supported in preview
- MaterialTheme(colors = palette) {
- MapContent()
+ override fun onStart() {
+ super.onStart()
+ mapView.onStart()
+ }
+
+ override fun onStop() {
+ mapView.onStop()
+ super.onStop()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ mapView.onResume()
+ }
+
+ override fun onDestroy() {
+ mapView.onDestroy()
+ super.onDestroy()
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ mapView.onSaveInstanceState(outState)
+ super.onSaveInstanceState(outState)
}
}
+
+
+
+
diff --git a/app/src/main/java/com/geeksville/mesh/ui/ScreenFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/ScreenFragment.kt
new file mode 100644
index 000000000..d707ce881
--- /dev/null
+++ b/app/src/main/java/com/geeksville/mesh/ui/ScreenFragment.kt
@@ -0,0 +1,21 @@
+package com.geeksville.mesh.ui
+
+import androidx.fragment.app.Fragment
+import com.geeksville.android.GeeksvilleApplication
+
+/**
+ * A fragment that represents a current 'screen' in our app.
+ *
+ * Useful for tracking analytics
+ */
+open class ScreenFragment(private val screenName: String) : Fragment() {
+ override fun onResume() {
+ super.onResume()
+ GeeksvilleApplication.analytics.sendScreenView(screenName)
+ }
+
+ override fun onPause() {
+ GeeksvilleApplication.analytics.endScreenView()
+ super.onPause()
+ }
+}
diff --git a/app/src/main/res/layout/map_view.xml b/app/src/main/res/layout/map_view.xml
index a77c3ecf9..bfdb57e79 100644
--- a/app/src/main/res/layout/map_view.xml
+++ b/app/src/main/res/layout/map_view.xml
@@ -1,10 +1,17 @@
-
+ android:id="@+id/mapFrame">
+
+
+
+
\ No newline at end of file