Show distance to the user on the "Live now" screen

This commit is contained in:
Alex Sytnyk 2018-07-05 20:42:29 +03:00
parent dfa3e5c4bd
commit 34c17db447
2 changed files with 137 additions and 29 deletions

View file

@ -5,10 +5,17 @@ import android.graphics.drawable.Drawable
import android.widget.ImageView
import net.osmand.telegram.R
import net.osmand.telegram.TelegramApplication
import net.osmand.telegram.helpers.TelegramHelper.MessageOsmAndBotLocation
import org.drinkless.td.libcore.telegram.TdApi
object TelegramUiHelper {
fun setupPhoto(app: TelegramApplication, iv: ImageView?, photoPath: String?) {
fun setupPhoto(
app: TelegramApplication,
iv: ImageView?,
photoPath: String?,
placeholderId: Int = R.drawable.ic_group
) {
if (iv == null) {
return
}
@ -18,7 +25,7 @@ object TelegramUiHelper {
bitmap = app.uiUtils.getCircleBitmap(photoPath)
}
if (bitmap == null) {
drawable = app.uiUtils.getThemedIcon(R.drawable.ic_group)
drawable = app.uiUtils.getThemedIcon(placeholderId)
}
if (bitmap != null) {
iv.setImageBitmap(bitmap)
@ -26,4 +33,60 @@ object TelegramUiHelper {
iv.setImageDrawable(drawable)
}
}
fun messageToLocationItem(helper: TelegramHelper, message: TdApi.Message): LocationItem? {
val content = message.content
return when (content) {
is MessageOsmAndBotLocation -> botMessageToLocationItem(content)
is TdApi.MessageLocation -> locationMessageToLocationItem(helper, message)
else -> null
}
}
private fun botMessageToLocationItem(content: MessageOsmAndBotLocation): LocationItem? {
return if (content.isValid()) {
LocationItem().apply {
name = content.name
lat = content.lat
lon = content.lon
placeholderId = R.drawable.ic_group
}
} else {
null
}
}
private fun locationMessageToLocationItem(
helper: TelegramHelper,
message: TdApi.Message
): LocationItem? {
val user = helper.getUser(message.senderUserId) ?: return null
val content = message.content as TdApi.MessageLocation
return LocationItem().apply {
name = "${user.firstName} ${user.lastName}".trim()
if (name.isEmpty()) {
name = user.username
}
if (name.isEmpty()) {
name = user.phoneNumber
}
lat = content.location.latitude
lon = content.location.longitude
photoPath = helper.getUserPhotoPath(user)
placeholderId = R.drawable.ic_group
}
}
class LocationItem {
var name: String = ""
internal set
var lat: Double = 0.0
internal set
var lon: Double = 0.0
internal set
var photoPath: String? = null
internal set
var placeholderId: Int = 0
internal set
}
}

View file

@ -13,18 +13,24 @@ import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.ImageView
import android.widget.TextView
import net.osmand.Location
import net.osmand.telegram.R
import net.osmand.telegram.TelegramApplication
import net.osmand.telegram.TelegramLocationProvider.TelegramLocationListener
import net.osmand.telegram.helpers.TelegramHelper
import net.osmand.telegram.helpers.TelegramHelper.*
import net.osmand.telegram.helpers.TelegramUiHelper
import net.osmand.telegram.helpers.TelegramUiHelper.LocationItem
import net.osmand.telegram.utils.AndroidUtils
import net.osmand.telegram.utils.OsmandFormatter
import net.osmand.util.MapUtils
import org.drinkless.td.libcore.telegram.TdApi
private const val CHAT_VIEW_TYPE = 0
private const val CONTACT_VIEW_TYPE = 1
private const val LOCATION_ITEM_VIEW_TYPE = 1
class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessagesListener {
class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessagesListener,
TelegramLocationListener {
private val app: TelegramApplication
get() = activity?.application as TelegramApplication
@ -35,6 +41,8 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
private lateinit var adapter: LiveNowListAdapter
private var location: Location? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -53,11 +61,13 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
super.onResume()
updateList()
telegramHelper.addIncomingMessagesListener(this)
startLocationUpdate()
}
override fun onPause() {
super.onPause()
telegramHelper.removeIncomingMessagesListener(this)
stopLocationUpdate()
}
override fun onTelegramStatusChanged(
@ -92,17 +102,39 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
updateList()
}
override fun onTelegramError(code: Int, message: String) {
}
override fun onTelegramError(code: Int, message: String) {}
override fun onSendLiveLocationError(code: Int, message: String) {
}
override fun onSendLiveLocationError(code: Int, message: String) {}
override fun onReceiveChatLocationMessages(chatTitle: String, vararg messages: TdApi.Message) {
app.runInUIThread { updateList() }
}
override fun updateLocationMessages() {
override fun updateLocationMessages() {}
override fun updateLocation(location: Location?) {
val loc = this.location
val newLocation = loc == null && location != null
val locationChanged = loc != null && location != null
&& loc.latitude != location.latitude
&& loc.longitude != location.longitude
if (newLocation || locationChanged) {
this.location = location
updateLocationUi()
}
}
fun startLocationUpdate() {
app.locationProvider.addLocationListener(this)
updateLocationUi()
}
fun stopLocationUpdate() {
app.locationProvider.removeLocationListener(this)
}
private fun updateLocationUi() {
adapter.notifyDataSetChanged()
}
private fun updateList() {
@ -110,23 +142,33 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
for ((id, messages) in telegramHelper.getMessagesByChatIds()) {
telegramHelper.getChat(id)?.also { chat ->
res.add(chat)
val type = chat.type
if (type is TdApi.ChatTypeBasicGroup || type is TdApi.ChatTypeSupergroup) {
messages.forEach { message ->
if (message.content is MessageOsmAndBotLocation) {
res.add(message.content)
} else {
telegramHelper.getUser(message.senderUserId)?.also { res.add(it) }
}
}
} else if (type is TdApi.ChatTypePrivate && telegramHelper.getUser(type.userId)?.username == TelegramHelper.OSMAND_BOT_USERNAME) {
res.addAll(messages.filter { it.content is MessageOsmAndBotLocation })
if (needLocationItems(chat.type)) {
res.addAll(convertToLocationItems(messages))
}
}
}
adapter.items = res
}
private fun needLocationItems(type: TdApi.ChatType): Boolean {
return when (type) {
is TdApi.ChatTypeBasicGroup -> true
is TdApi.ChatTypeSupergroup -> true
is TdApi.ChatTypePrivate -> {
telegramHelper.getUser(type.userId)?.username == TelegramHelper.OSMAND_BOT_USERNAME
}
else -> false
}
}
private fun convertToLocationItems(messages: List<TdApi.Message>): List<LocationItem> {
return mutableListOf<LocationItem>().apply {
messages.forEach { message ->
TelegramUiHelper.messageToLocationItem(telegramHelper, message)?.also { add(it) }
}
}
}
inner class LiveNowListAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private val menuList =
@ -141,7 +183,7 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
override fun getItemViewType(position: Int): Int {
return when (items[position]) {
is TdApi.Chat -> CHAT_VIEW_TYPE
else -> CONTACT_VIEW_TYPE
else -> LOCATION_ITEM_VIEW_TYPE
}
}
@ -173,15 +215,18 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
holder.showOnMapState?.text = menuList[stateTextInd]
holder.bottomDivider?.visibility = if (nextItemIsUser) View.VISIBLE else View.GONE
holder.bottomShadow?.visibility = if (lastItem) View.VISIBLE else View.GONE
} else if (item is TdApi.User && holder is ContactViewHolder) {
TelegramUiHelper.setupPhoto(app, holder.icon, telegramHelper.getUserPhotoPath(item))
holder.title?.text = "${item.firstName} ${item.lastName}"
holder.description?.text = "User description" // FIXME
holder.bottomShadow?.visibility = if (lastItem) View.VISIBLE else View.GONE
} else if (item is MessageOsmAndBotLocation && holder is ContactViewHolder) {
holder.icon?.setImageDrawable(app.uiUtils.getThemedIcon(R.drawable.ic_group))
} else if (item is LocationItem && holder is ContactViewHolder) {
TelegramUiHelper.setupPhoto(app, holder.icon, item.photoPath, item.placeholderId)
holder.title?.text = item.name
holder.description?.text = "Location from osmand_bot" // FIXME
if (location != null) {
val dist = MapUtils.getDistance(
location!!.latitude, location!!.longitude,
item.lat, item.lon
).toFloat()
holder.description?.text = OsmandFormatter.getFormattedDistance(dist, app)
} else {
holder.description?.text = "Current location is not available"
}
holder.bottomShadow?.visibility = if (lastItem) View.VISIBLE else View.GONE
}
}