Bimba.git

ref: 5cb16913cd9ec8d0c721b7a7c7731ba3a35d52fc

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
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

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 preferences: SharedPreferences

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

		preferences = 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)
					}
					startActivity(intent)
				}
				is Line -> {
					TODO("start line graph activity")
				}
			}
		}
		binding.resultsRecycler.adapter = adapter
		setSupportActionBar(binding.topAppBar)

		WindowCompat.setDecorFitsSystemWindows(window, false)

		@Suppress("DEPRECATION")  // fix_later getSerializable in API>=33
		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 = preferences.getString("host", "bimba.apiote.xyz")!!
				getItemsByQuery(
					Server(
						host, preferences.getString("token", "")!!,
						preferences.getString("${host}_feeds", "")!!
					), query
				)
			}
		}
	}

	@SuppressLint("MissingPermission")
	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) {
		val code = OpenLocationCode.encode(location.latitude, location.longitude)
		val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
		locationManager.removeUpdates(this)
		val host = preferences.getString("host", "bimba.apiote.xyz")!!
		getItemsByLocation(
			Server(
				host, preferences.getString("token", "")!!,
				preferences.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(error-handling) show empty state
			} else {
				updateItems(unmarshallItemResponse(itemsStream))
			}
		}
	}

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

	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")
				}
			}
		}
	}

}