Merge pull request #5881 from osmandapp/TravelUiImprovements

SetTimeDialog UI Improvements
This commit is contained in:
Alexander Sytnyk 2018-08-16 14:29:55 +03:00 committed by GitHub
commit 7d3ea473e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 128 additions and 31 deletions

View file

@ -1,4 +1,7 @@
<resources> <resources>
<string name="time_ago">ago</string>
<string name="last_response">Last response</string>
<string name="shared_string_group">Group</string>
<string name="logout_no_internet_msg">To properly log out from your Telegram account, the Internet is needed.</string> <string name="logout_no_internet_msg">To properly log out from your Telegram account, the Internet is needed.</string>
<string name="shared_string_close">Close</string> <string name="shared_string_close">Close</string>
<string name="disconnect_from_telegram_desc">To invoke access to your Telegram account from OsmAnd, open Telegram, go to Settings - Privacy and Security - Sessions and terminate OsmAnd Telegram session. After that, OsmAnd Location Sharing will no longer have access to your account, and you will not be able to use this app until you log in again.</string> <string name="disconnect_from_telegram_desc">To invoke access to your Telegram account from OsmAnd, open Telegram, go to Settings - Privacy and Security - Sessions and terminate OsmAnd Telegram session. After that, OsmAnd Location Sharing will no longer have access to your account, and you will not be able to use this app until you log in again.</string>

View file

@ -54,7 +54,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
val messages = telegramHelper.getMessages() val messages = telegramHelper.getMessages()
for (message in messages) { for (message in messages) {
val date = Math.max(message.date, message.editDate) * 1000L val date = Math.max(message.date, message.editDate) * 1000L
val expired = System.currentTimeMillis() - date > app.settings.locHistoryTime val expired = System.currentTimeMillis() - date > app.settings.locHistoryTime * 1000L
if (expired) { if (expired) {
removeMapPoint(message.chatId, message) removeMapPoint(message.chatId, message)
} }

View file

@ -177,6 +177,8 @@ class TelegramHelper private constructor() {
return chat.type is TdApi.ChatTypeSupergroup || chat.type is TdApi.ChatTypeBasicGroup return chat.type is TdApi.ChatTypeSupergroup || chat.type is TdApi.ChatTypeBasicGroup
} }
fun getLastUpdatedTime(message: TdApi.Message) = Math.max(message.editDate, message.date)
fun isPrivateChat(chat: TdApi.Chat): Boolean = chat.type is TdApi.ChatTypePrivate fun isPrivateChat(chat: TdApi.Chat): Boolean = chat.type is TdApi.ChatTypePrivate
private fun isChannel(chat: TdApi.Chat): Boolean { private fun isChannel(chat: TdApi.Chat): Boolean {
@ -485,9 +487,7 @@ class TelegramHelper private constructor() {
val viaBot = isOsmAndBot(message.viaBotUserId) val viaBot = isOsmAndBot(message.viaBotUserId)
val oldContent = message.content val oldContent = message.content
if (oldContent is TdApi.MessageText) { if (oldContent is TdApi.MessageText) {
message.content = parseOsmAndBotLocation(oldContent.text.text).apply { message.content = parseOsmAndBotLocation(oldContent.text.text)
created = message.date
}
} else if (oldContent is TdApi.MessageLocation && (fromBot || viaBot)) { } else if (oldContent is TdApi.MessageLocation && (fromBot || viaBot)) {
message.content = parseOsmAndBotLocation(message) message.content = parseOsmAndBotLocation(message)
} }
@ -761,13 +761,7 @@ class TelegramHelper private constructor() {
name = getOsmAndBotDeviceName(message) name = getOsmAndBotDeviceName(message)
lat = messageLocation.location.latitude lat = messageLocation.location.latitude
lon = messageLocation.location.longitude lon = messageLocation.location.longitude
created = message.date lastUpdated = getLastUpdatedTime(message)
val date = message.editDate
lastUpdated = if (date != 0) {
date
} else {
message.date
}
} }
} }
@ -777,7 +771,6 @@ class TelegramHelper private constructor() {
name = oldContent.name name = oldContent.name
lat = messageLocation.location.latitude lat = messageLocation.location.latitude
lon = messageLocation.location.longitude lon = messageLocation.location.longitude
created = oldContent.created
lastUpdated = (System.currentTimeMillis() / 1000).toInt() lastUpdated = (System.currentTimeMillis() / 1000).toInt()
} }
} }
@ -1069,9 +1062,7 @@ class TelegramHelper private constructor() {
synchronized(message) { synchronized(message) {
val newContent = updateMessageContent.newContent val newContent = updateMessageContent.newContent
message.content = if (newContent is TdApi.MessageText) { message.content = if (newContent is TdApi.MessageText) {
val messageOsmAndBotLocation = parseOsmAndBotLocation(newContent.text.text) parseOsmAndBotLocation(newContent.text.text)
messageOsmAndBotLocation.created = message.date
messageOsmAndBotLocation
} else if (newContent is TdApi.MessageLocation && } else if (newContent is TdApi.MessageLocation &&
(isOsmAndBot(message.senderUserId) || isOsmAndBot(message.viaBotUserId))) { (isOsmAndBot(message.senderUserId) || isOsmAndBot(message.viaBotUserId))) {
parseOsmAndBotLocationContent(message.content as MessageOsmAndBotLocation, newContent) parseOsmAndBotLocationContent(message.content as MessageOsmAndBotLocation, newContent)

View file

@ -54,8 +54,7 @@ object TelegramUiHelper {
val type = chat.type val type = chat.type
val message = messages.firstOrNull() val message = messages.firstOrNull()
if (message != null) { if (message != null) {
res.lastUpdated = message.editDate res.lastUpdated = helper.getLastUpdatedTime(message)
res.created = message.date
} }
if (type is TdApi.ChatTypePrivate || type is TdApi.ChatTypeSecret) { if (type is TdApi.ChatTypePrivate || type is TdApi.ChatTypeSecret) {
val userId = getUserIdFromChatType(type) val userId = getUserIdFromChatType(type)
@ -125,7 +124,6 @@ object TelegramUiHelper {
latLon = LatLon(content.lat, content.lon) latLon = LatLon(content.lat, content.lon)
placeholderId = R.drawable.img_user_picture placeholderId = R.drawable.img_user_picture
lastUpdated = content.lastUpdated lastUpdated = content.lastUpdated
created = content.created
} }
} else { } else {
null null
@ -147,8 +145,7 @@ object TelegramUiHelper {
photoPath = helper.getUserPhotoPath(user) photoPath = helper.getUserPhotoPath(user)
placeholderId = R.drawable.img_user_picture placeholderId = R.drawable.img_user_picture
userId = message.senderUserId userId = message.senderUserId
lastUpdated = message.editDate lastUpdated = helper.getLastUpdatedTime(message)
created = message.date
} }
} }
@ -168,8 +165,6 @@ object TelegramUiHelper {
internal set internal set
var lastUpdated: Int = 0 var lastUpdated: Int = 0
internal set internal set
var created: Int = 0
internal set
abstract fun canBeOpenedOnMap(): Boolean abstract fun canBeOpenedOnMap(): Boolean

View file

@ -361,12 +361,12 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
} }
} }
private fun getListItemLiveTimeDescr(item: ListItem):String { private fun getListItemLiveTimeDescr(item: ListItem): String {
return getString(R.string.shared_string_live) + val formattedTime = OsmandFormatter.getFormattedDuration(app, getListItemLiveTime(item))
": ${OsmandFormatter.getFormattedDuration(app, getListItemLiveTime(item))}" return getString(R.string.last_response) + ": $formattedTime " + getString(R.string.time_ago)
} }
private fun getListItemLiveTime(item: ListItem): Long = (System.currentTimeMillis() / 1000) - item.created private fun getListItemLiveTime(item: ListItem): Long = (System.currentTimeMillis() / 1000) - item.lastUpdated
private fun showPopupMenu(holder: ChatViewHolder, chatId: Long) { private fun showPopupMenu(holder: ChatViewHolder, chatId: Long) {
val ctx = holder.itemView.context val ctx = holder.itemView.context

View file

@ -577,23 +577,25 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
} }
holder.stopSharingDescr?.apply { holder.stopSharingDescr?.apply {
visibility = View.VISIBLE visibility = getStopSharingVisibility(expiresIn)
text = "${getText(R.string.stop_at)}:" text = "${getText(R.string.stop_at)}:"
} }
holder.stopSharingFirstPart?.apply { holder.stopSharingFirstPart?.apply {
visibility = View.VISIBLE visibility = getStopSharingVisibility(expiresIn)
text = OsmandFormatter.getFormattedTime(expiresIn) text = OsmandFormatter.getFormattedTime(expiresIn)
} }
holder.stopSharingSecondPart?.apply { holder.stopSharingSecondPart?.apply {
visibility = View.VISIBLE visibility = getStopSharingVisibility(expiresIn)
text = "(${getString(R.string.in_time, text = "(${getString(R.string.in_time,
OsmandFormatter.getFormattedDuration(context!!, expiresIn, true))})" OsmandFormatter.getFormattedDuration(context!!, expiresIn, true))})"
} }
} }
} }
private fun getStopSharingVisibility(expiresIn: Long) = if (expiresIn > 0) View.VISIBLE else View.INVISIBLE
private fun removeItem(chat: TdApi.Chat) { private fun removeItem(chat: TdApi.Chat) {
chats.remove(chat) chats.remove(chat)
if (chats.isEmpty()) { if (chats.isEmpty()) {

View file

@ -12,16 +12,23 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import net.osmand.Location
import net.osmand.data.LatLon
import net.osmand.telegram.R import net.osmand.telegram.R
import net.osmand.telegram.TelegramApplication import net.osmand.telegram.TelegramApplication
import net.osmand.telegram.TelegramLocationProvider.TelegramLocationListener
import net.osmand.telegram.TelegramLocationProvider.TelegramCompassListener
import net.osmand.telegram.helpers.ShareLocationHelper import net.osmand.telegram.helpers.ShareLocationHelper
import net.osmand.telegram.helpers.TelegramUiHelper import net.osmand.telegram.helpers.TelegramUiHelper
import net.osmand.telegram.ui.SetTimeDialogFragment.SetTimeListAdapter.ChatViewHolder import net.osmand.telegram.ui.SetTimeDialogFragment.SetTimeListAdapter.ChatViewHolder
import net.osmand.telegram.utils.AndroidUtils import net.osmand.telegram.utils.AndroidUtils
import net.osmand.telegram.utils.OsmandFormatter
import net.osmand.telegram.utils.UiUtils
import net.osmand.util.MapUtils
import org.drinkless.td.libcore.telegram.TdApi import org.drinkless.td.libcore.telegram.TdApi
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
class SetTimeDialogFragment : DialogFragment() { class SetTimeDialogFragment : DialogFragment(), TelegramLocationListener, TelegramCompassListener {
private val app: TelegramApplication private val app: TelegramApplication
get() = activity?.application as TelegramApplication get() = activity?.application as TelegramApplication
@ -29,6 +36,7 @@ class SetTimeDialogFragment : DialogFragment() {
private val telegramHelper get() = app.telegramHelper private val telegramHelper get() = app.telegramHelper
private val settings get() = app.settings private val settings get() = app.settings
private lateinit var locationViewCache: UiUtils.UpdateLocationViewCache
private val adapter = SetTimeListAdapter() private val adapter = SetTimeListAdapter()
private lateinit var timeForAllTitle: TextView private lateinit var timeForAllTitle: TextView
@ -36,6 +44,10 @@ class SetTimeDialogFragment : DialogFragment() {
private val chatLivePeriods = HashMap<Long, Long>() private val chatLivePeriods = HashMap<Long, Long>()
private var location: Location? = null
private var heading: Float? = null
private var locationUiUpdateAllowed: Boolean = true
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setStyle(DialogFragment.STYLE_NO_FRAME, R.style.AppTheme_NoActionbar) setStyle(DialogFragment.STYLE_NO_FRAME, R.style.AppTheme_NoActionbar)
@ -66,6 +78,12 @@ class SetTimeDialogFragment : DialogFragment() {
view.findViewById<RecyclerView>(R.id.recycler_view).apply { view.findViewById<RecyclerView>(R.id.recycler_view).apply {
layoutManager = LinearLayoutManager(context) layoutManager = LinearLayoutManager(context)
adapter = this@SetTimeDialogFragment.adapter adapter = this@SetTimeDialogFragment.adapter
addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
locationUiUpdateAllowed = newState == RecyclerView.SCROLL_STATE_IDLE
}
})
} }
view.findViewById<TextView>(R.id.secondary_btn).apply { view.findViewById<TextView>(R.id.secondary_btn).apply {
@ -98,9 +116,16 @@ class SetTimeDialogFragment : DialogFragment() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
locationViewCache = app.uiUtils.getUpdateLocationViewCache()
startLocationUpdate()
updateList() updateList()
} }
override fun onPause() {
super.onPause()
stopLocationUpdate()
}
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
val chats = mutableListOf<Long>() val chats = mutableListOf<Long>()
@ -111,6 +136,47 @@ class SetTimeDialogFragment : DialogFragment() {
outState.putLongArray(CHATS_KEY, chats.toLongArray()) outState.putLongArray(CHATS_KEY, chats.toLongArray())
} }
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()
}
}
override fun updateCompassValue(value: Float) {
// 99 in next line used to one-time initialize arrows (with reference vs. fixed-north direction)
// on non-compass devices
val lastHeading = heading ?: 99f
heading = value
if (Math.abs(MapUtils.degreesDiff(lastHeading.toDouble(), value.toDouble())) > 5) {
updateLocationUi()
} else {
heading = lastHeading
}
}
private fun startLocationUpdate() {
app.locationProvider.addLocationListener(this)
app.locationProvider.addCompassListener(this)
updateLocationUi()
}
private fun stopLocationUpdate() {
app.locationProvider.removeLocationListener(this)
app.locationProvider.removeCompassListener(this)
}
private fun updateLocationUi() {
if (locationUiUpdateAllowed) {
app.runInUIThread { adapter.notifyDataSetChanged() }
}
}
private fun readFromBundle(bundle: Bundle?) { private fun readFromBundle(bundle: Bundle?) {
chatLivePeriods.clear() chatLivePeriods.clear()
bundle?.getLongArray(CHATS_KEY)?.also { bundle?.getLongArray(CHATS_KEY)?.also {
@ -216,7 +282,35 @@ class SetTimeDialogFragment : DialogFragment() {
TelegramUiHelper.setupPhoto(app, holder.icon, chat.photo?.small?.local?.path, placeholderId, false) TelegramUiHelper.setupPhoto(app, holder.icon, chat.photo?.small?.local?.path, placeholderId, false)
holder.title?.text = chat.title holder.title?.text = chat.title
holder.description?.visibility = View.INVISIBLE
if (telegramHelper.isGroup(chat)) {
holder.locationViewContainer?.visibility = View.GONE
holder.description?.visibility = View.VISIBLE
holder.description?.text = getString(R.string.shared_string_group)
} else {
val message = telegramHelper.getChatMessages(chat.id).firstOrNull()
val content = message?.content
if (message != null && content is TdApi.MessageLocation && (location != null && content.location != null)) {
val lastUpdated = telegramHelper.getLastUpdatedTime(message)
holder.description?.visibility = View.VISIBLE
holder.description?.text = getListItemLiveTimeDescr(lastUpdated)
holder.locationViewContainer?.visibility = View.VISIBLE
locationViewCache.outdatedLocation = System.currentTimeMillis() / 1000 -
lastUpdated > settings.staleLocTime
app.uiUtils.updateLocationView(
holder.directionIcon,
holder.distanceText,
LatLon(content.location.latitude, content.location.longitude),
locationViewCache
)
} else {
holder.locationViewContainer?.visibility = View.GONE
holder.description?.visibility = View.INVISIBLE
}
}
holder.textInArea?.apply { holder.textInArea?.apply {
visibility = View.VISIBLE visibility = View.VISIBLE
chatLivePeriods[chat.id]?.also { text = formatLivePeriod(it) } chatLivePeriods[chat.id]?.also { text = formatLivePeriod(it) }
@ -229,9 +323,21 @@ class SetTimeDialogFragment : DialogFragment() {
override fun getItemCount() = chats.size override fun getItemCount() = chats.size
private fun getListItemLiveTimeDescr(lastUpdated: Int): String {
val formattedTime = OsmandFormatter.getFormattedDuration(app, getListItemLiveTime(lastUpdated))
return "$formattedTime " + getString(R.string.time_ago)
}
private fun getListItemLiveTime(lastUpdated: Int): Long {
return (System.currentTimeMillis() / 1000) - lastUpdated
}
inner class ChatViewHolder(val view: View) : RecyclerView.ViewHolder(view) { inner class ChatViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
val icon: ImageView? = view.findViewById(R.id.icon) val icon: ImageView? = view.findViewById(R.id.icon)
val title: TextView? = view.findViewById(R.id.title) val title: TextView? = view.findViewById(R.id.title)
val directionIcon: ImageView? = view.findViewById(R.id.direction_icon)
val distanceText: TextView? = view.findViewById(R.id.distance_text)
val locationViewContainer: View? = view.findViewById(R.id.location_view_container)
val description: TextView? = view.findViewById(R.id.description) val description: TextView? = view.findViewById(R.id.description)
val textInArea: TextView? = view.findViewById(R.id.text_in_area) val textInArea: TextView? = view.findViewById(R.id.text_in_area)
val bottomShadow: View? = view.findViewById(R.id.bottom_shadow) val bottomShadow: View? = view.findViewById(R.id.bottom_shadow)