Bimba.git

ref: 0f3ae9e13096218a22641ba4684cd48d77f987e3

app/src/main/java/ml/adamsprogs/bimba/search/ResultsActivity.kt


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package ml.adamsprogs.bimba.search

import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.openlocationcode.OpenLocationCode
import kotlinx.coroutines.*
import ml.adamsprogs.bimba.departures.DeparturesActivity
import ml.adamsprogs.bimba.api.*
import ml.adamsprogs.bimba.databinding.ActivityResultsBinding
import java.io.InputStream

@SuppressLint("MissingPermission")
class ResultsActivity : AppCompatActivity(), LocationListener {
	enum class Mode {
		MODE_LOCATION, MODE_SEARCH
	}

	private var _binding: ActivityResultsBinding? = null

	private val binding get() = _binding!!

	private lateinit var adapter: BimbaResultsAdapter

	private lateinit var shp: SharedPreferences

	override fun onCreate(savedInstanceState: Bundle?) {
		super.onCreate(savedInstanceState)
		_binding = ActivityResultsBinding.inflate(layoutInflater)
		setContentView(binding.root)

		shp = getSharedPreferences("shp", MODE_PRIVATE)

		binding.resultsRecycler.layoutManager = LinearLayoutManager(this)
		adapter = BimbaResultsAdapter(layoutInflater, this, listOf()) {
			when (it) {
				is Stop -> {
					val intent = Intent(this, DeparturesActivity::class.java).apply {
						putExtra("code", it.code)
						putExtra("name", it.name)
						// todo line, date, etc
					}
					startActivity(intent)
				}
				is Line -> {
					TODO("start line graph actvity")
				}
			}
		}
		binding.resultsRecycler.adapter = adapter
		setSupportActionBar(binding.topAppBar)

		WindowCompat.setDecorFitsSystemWindows(window, false)

		when (intent.extras?.get("mode")) {
			Mode.MODE_LOCATION -> {
				supportActionBar?.title = "Stops nearby"
				locate()
			}
			Mode.MODE_SEARCH -> {
				val query = intent.extras?.getString("query")!!
				supportActionBar?.title = "Results for ‘$query"
				val host = shp.getString("host", "bimba.apiote.xyz")!!
				getItemsByQuery(
					Server(
						host, shp.getString("token", "")!!,
						shp.getString("${host}_feeds", "")!!
					), query
				)
			}
		}
	}

	private fun locate() {  // todo also on back to this activity (onRestart?)
		val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
		locationManager.requestLocationUpdates(
			LocationManager.GPS_PROVIDER, 5000, 10f, this
		)
		locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
			?.let { onLocationChanged(it) }
	}

	override fun onLocationChanged(location: Location) {
		Log.v("Location", "found $location")
		val code = OpenLocationCode.encode(location.latitude, location.longitude)
		val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
		locationManager.removeUpdates(this)
		val host = shp.getString("host", "bimba.apiote.xyz")!!
		getItemsByLocation(
			Server(
				host, shp.getString("token", "")!!,
				shp.getString("${host}_feeds", "")!!
			), code
		)
	}

	override fun onDestroy() {  // todo also on hide this activity (onPause?)
		super.onDestroy()
		val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
		locationManager.removeUpdates(this)
	}

	private fun getItemsByQuery(server: Server, query: String) {
		MainScope().launch {
			val itemsStream = queryItems(server, query)
			if (itemsStream == null) {
				// todo show empty state
			} else {
				updateItems(unmarshallItemResponse(itemsStream))
			}
			Log.v("RESPONSE", "getItemsByQuery")
		}
	}

	private fun getItemsByLocation(server: Server, plusCode: String) {
		Log.v("RESPONSE", "getting ItemsByLocation")
		MainScope().launch {
			val itemsStream = locateItems(server, plusCode)
			if (itemsStream == null) {
				// todo show empty state
			} else {
				updateItems(unmarshallItemResponse(itemsStream))
			}
			Log.v("RESPONSE", "getItemsByLocation")
		}
	}

	private fun updateItems(items: List<Item>) {
		binding.resultsProgress.visibility = View.GONE
		binding.resultsRecycler.visibility = View.VISIBLE
		adapter.update(items)
	}

	private suspend fun unmarshallItemResponse(stream: InputStream): List<Item> {
		return withContext(Dispatchers.IO) {
			when (val response = ItemsResponse.unmarshall(stream)) {
				is ItemsSuccess -> {
					return@withContext response.items
				}
				else -> {
					TODO("Error response")
				}
			}
		}
	}

}