diff --git a/OsmAnd-telegram/res/layout/fragement_settings_dialog.xml b/OsmAnd-telegram/res/layout/fragement_settings_dialog.xml index 5d2bacf752..e063c5ee3d 100644 --- a/OsmAnd-telegram/res/layout/fragement_settings_dialog.xml +++ b/OsmAnd-telegram/res/layout/fragement_settings_dialog.xml @@ -74,6 +74,35 @@ + + + + + + + + + + diff --git a/OsmAnd-telegram/res/layout/item_with_descr_and_right_switch.xml b/OsmAnd-telegram/res/layout/item_with_descr_and_right_switch.xml new file mode 100644 index 0000000000..4969b003ed --- /dev/null +++ b/OsmAnd-telegram/res/layout/item_with_descr_and_right_switch.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + diff --git a/OsmAnd-telegram/res/layout/live_now_chat_card.xml b/OsmAnd-telegram/res/layout/live_now_chat_card.xml index a72f3a80fe..26714c98a4 100644 --- a/OsmAnd-telegram/res/layout/live_now_chat_card.xml +++ b/OsmAnd-telegram/res/layout/live_now_chat_card.xml @@ -186,6 +186,28 @@ + + + + + + - + android:layout_gravity="center_vertical" + android:textColor="?android:attr/textColorSecondary" + android:textSize="@dimen/hint_text_size" + app:typeface="@string/font_roboto_regular" + tools:text="@string/expire_at" /> - - - - - - - - - - - - - - - - - + android:layout_gravity="center_vertical" + android:text="@string/gps_points" + android:textColor="?android:attr/textColorSecondary" + android:textSize="@dimen/hint_text_size" + app:typeface="@string/font_roboto_regular" /> diff --git a/OsmAnd-telegram/res/layout/user_list_item.xml b/OsmAnd-telegram/res/layout/user_list_item.xml index 3ec45fd1d9..8fc125f4c5 100644 --- a/OsmAnd-telegram/res/layout/user_list_item.xml +++ b/OsmAnd-telegram/res/layout/user_list_item.xml @@ -15,7 +15,8 @@ @@ -106,6 +107,28 @@ + + + + + + 89dp 48dp + 42dp 56dp 48dp @@ -82,7 +83,7 @@ 14sp 16sp - 12sp + 13sp 15sp diff --git a/OsmAnd-telegram/res/values/strings.xml b/OsmAnd-telegram/res/values/strings.xml index d93be06214..f5c0e0de4d 100644 --- a/OsmAnd-telegram/res/values/strings.xml +++ b/OsmAnd-telegram/res/values/strings.xml @@ -1,4 +1,8 @@ + Received GPX points: %1$s + Appearance + Show GPS points + Show quantity of collected and sent GPS points. Please update OsmAnd to view data on the map Update sent (%1$d in buffer) diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt index 53c227f0d6..0e0ea2fa93 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt @@ -15,6 +15,7 @@ import net.osmand.telegram.utils.OsmandApiUtils import net.osmand.telegram.utils.OsmandFormatter import net.osmand.telegram.utils.OsmandFormatter.MetricsConstants import net.osmand.telegram.utils.OsmandFormatter.SpeedConstants +import net.osmand.telegram.utils.OsmandLocationUtils import org.drinkless.td.libcore.telegram.TdApi import org.json.JSONArray import org.json.JSONException @@ -29,7 +30,7 @@ const val SHARE_DEVICES_KEY = "devices" private val SEND_MY_LOC_VALUES_SEC = listOf(1L, 2L, 3L, 5L, 10L, 15L, 30L, 60L, 90L, 2 * 60L, 3 * 60L, 5 * 60L) private val STALE_LOC_VALUES_SEC = - listOf(1 * 60L, 2 * 60L, 5 * 60L, 10 * 60L, 15 * 60L, 30 * 60L, 60 * 60L) + listOf(1 * 60L, 2 * 60L, 5 * 60L, 10 * 60L, 15 * 60L, 30 * 60L, 60 * 60L, 60*60*24L) private val LOC_HISTORY_VALUES_SEC = listOf( 5 * 60L, 15 * 60L, @@ -40,7 +41,8 @@ private val LOC_HISTORY_VALUES_SEC = listOf( 5 * 60 * 60L, 8 * 60 * 60L, 12 * 60 * 60L, - 24 * 60 * 60L + 24 * 60 * 60L, + 7*24 * 60 * 60L ) const val SHARE_TYPE_MAP = "Map" @@ -82,6 +84,8 @@ private const val BATTERY_OPTIMISATION_ASKED = "battery_optimisation_asked" private const val MONITORING_ENABLED = "monitoring_enabled" +private const val SHOW_GPS_POINTS = "show_gps_points" + private const val SHARING_INITIALIZATION_TIME = 60 * 2L // 2 minutes private const val WAITING_TDLIB_TIME = 30 // 2 seconds @@ -119,6 +123,8 @@ class TelegramSettings(private val app: TelegramApplication) { var monitoringEnabled = false + var showGpsPoints = false + init { updatePrefs() read() @@ -259,7 +265,7 @@ class TelegramSettings(private val app: TelegramApplication) { fun updateShareInfo(message: TdApi.Message) { val shareInfo = shareChatsInfo[message.chatId] val content = message.content - val isOsmAndBot = app.telegramHelper.isOsmAndBot(message.senderUserId) || app.telegramHelper.isOsmAndBot(message.viaBotUserId) + val isOsmAndBot = app.telegramHelper.isOsmAndBot(OsmandLocationUtils.getSenderMessageId(message)) || app.telegramHelper.isOsmAndBot(message.viaBotUserId) if (shareInfo != null) { when (content) { is TdApi.MessageLocation -> { @@ -513,6 +519,8 @@ class TelegramSettings(private val app: TelegramApplication) { edit.putBoolean(MONITORING_ENABLED, monitoringEnabled) + edit.putBoolean(SHOW_GPS_POINTS, showGpsPoints) + val jArray = convertShareChatsInfoToJson() if (jArray != null) { edit.putString(SHARE_CHATS_INFO_KEY, jArray.toString()) @@ -572,6 +580,8 @@ class TelegramSettings(private val app: TelegramApplication) { batteryOptimisationAsked = prefs.getBoolean(BATTERY_OPTIMISATION_ASKED,false) monitoringEnabled = prefs.getBoolean(MONITORING_ENABLED,false) + + showGpsPoints = prefs.getBoolean(SHOW_GPS_POINTS,false) } private fun convertShareDevicesToJson():JSONObject?{ diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt index 814d56c2d4..d182cf3607 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt @@ -56,6 +56,10 @@ class LocationMessages(val app: TelegramApplication) { return dbHelper.getIngoingUserLocations(start, end) } + fun getIngoingUserLocationsInChat(userId: Int, chatId: Long, deviceName: String, start: Long, end: Long): UserLocations? { + return dbHelper.getIngoingUserLocationsInChat(userId, chatId, deviceName, start, end) + } + fun getMessagesForUserInChat(userId: Int, chatId: Long, deviceName: String, start: Long, end: Long): List { return dbHelper.getMessagesForUserInChat(userId, chatId,deviceName, start, end) } @@ -77,9 +81,9 @@ class LocationMessages(val app: TelegramApplication) { val type = OsmandLocationUtils.getMessageType(message) val content = OsmandLocationUtils.parseMessageContent(message, app.telegramHelper) val deviceName = if (content is OsmandLocationUtils.MessageOsmAndBotLocation) content.deviceName else "" - val newItem = LocationHistoryPoint(message.senderUserId, message.chatId, type, deviceName) + val newItem = LocationHistoryPoint(OsmandLocationUtils.getSenderMessageId(message), message.chatId, type, deviceName) val previousMessageLatLon = lastLocationPoints[newItem] - val locationMessage = OsmandLocationUtils.createLocationMessage(message, app.telegramHelper, content, previousMessageLatLon) + val locationMessage = OsmandLocationUtils.createLocationMessage(message, content, previousMessageLatLon) if (locationMessage != null) { dbHelper.addLocationMessage(locationMessage) lastLocationPoints[newItem] = LatLon(locationMessage.lat, locationMessage.lon) @@ -219,6 +223,35 @@ class LocationMessages(val app: TelegramApplication) { return res } + internal fun getIngoingUserLocationsInChat(userId: Int, chatId: Long, deviceName: String,start: Long, end: Long): UserLocations? { + val userLocationsMap: MutableMap> = mutableMapOf() + val userLocations = UserLocations(userId,chatId,deviceName,userLocationsMap) + val whereDeviceQuery = if (deviceName.isNotEmpty()) "AND $COL_DEVICE_NAME = ?" else "" + val args = if (deviceName.isNotEmpty()) arrayOf(userId.toString(), chatId.toString(), deviceName) else arrayOf(userId.toString(), chatId.toString()) + readableDatabase?.rawQuery("$TIMELINE_TABLE_SELECT WHERE $COL_USER_ID = ? AND $COL_CHAT_ID = ? $whereDeviceQuery AND $COL_TIME BETWEEN $start AND $end ORDER BY $COL_TYPE DESC, $COL_TIME ", args)?.apply { + if (moveToFirst()) { + var segment: UserTrkSegment? = null + do { + val locationMessage = readLocationMessage(this@apply) + if (segment == null || segment.type != locationMessage.type || locationMessage.time - segment.maxTime > 30 * 1000 * 60) { + segment = UserTrkSegment(mutableListOf(), 0.0, locationMessage.type, locationMessage.time, locationMessage.time) + if (userLocationsMap[segment.type] == null) { + userLocationsMap[segment.type] = mutableListOf() + } + userLocationsMap[segment.type]?.add(segment) + } + if (segment.points.size > 0) { + segment.distance += MapUtils.getDistance(locationMessage.lat, locationMessage.lon, segment.points.last().lat, segment.points.last().lon) + } + segment.maxTime = locationMessage.time + segment.points.add(locationMessage) + } while (moveToNext()) + } + close() + } + return userLocations + } + internal fun getMessagesForUserInChat(userId: Int, chatId: Long, deviceName: String, start: Long, end: Long): List { val res = arrayListOf() val whereDeviceQuery = if (deviceName.isNotEmpty()) "AND $COL_DEVICE_NAME = ?" else "" diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShowLocationHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShowLocationHelper.kt index 1f05580062..baa27e4bd0 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShowLocationHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShowLocationHelper.kt @@ -84,7 +84,7 @@ class ShowLocationHelper(private val app: TelegramApplication) { if (chatTitle != null && (content is TdApi.MessageLocation || (content is MessageUserLocation && content.isValid()))) { var userName = "" var photoPath: String? = null - val user = telegramHelper.getUser(message.senderUserId) + val user = telegramHelper.getUser(OsmandLocationUtils.getSenderMessageId(message)) if (user != null) { userName = "${user.firstName} ${user.lastName}".trim() if (userName.isEmpty()) { @@ -100,7 +100,7 @@ class ShowLocationHelper(private val app: TelegramApplication) { } } if (userName.isEmpty()) { - userName = message.senderUserId.toString() + userName = OsmandLocationUtils.getSenderMessageId(message).toString() } setupMapLayer() val params = generatePointParams(photoPath, stale) @@ -111,10 +111,10 @@ class ShowLocationHelper(private val app: TelegramApplication) { } if (aLatLon != null) { if (update) { - osmandAidlHelper.updateMapPoint(MAP_LAYER_ID, "${chatId}_${message.senderUserId}", userName, userName, + osmandAidlHelper.updateMapPoint(MAP_LAYER_ID, "${chatId}_${OsmandLocationUtils.getSenderMessageId(message)}", userName, userName, chatTitle, Color.WHITE, aLatLon, null, params) } else { - osmandAidlHelper.addMapPoint(MAP_LAYER_ID, "${chatId}_${message.senderUserId}", userName, userName, + osmandAidlHelper.addMapPoint(MAP_LAYER_ID, "${chatId}_${OsmandLocationUtils.getSenderMessageId(message)}", userName, userName, chatTitle, Color.WHITE, aLatLon, null, params) } } @@ -148,7 +148,7 @@ class ShowLocationHelper(private val app: TelegramApplication) { fun hideMessages(messages: List) { osmandAidlHelper.execOsmandApi { for (message in messages) { - val user = telegramHelper.getUser(message.senderUserId) + val user = telegramHelper.getUser(OsmandLocationUtils.getSenderMessageId(message)) if (user != null) { removeMapPoint(message.chatId, message) } @@ -277,7 +277,7 @@ class ShowLocationHelper(private val app: TelegramApplication) { private fun removeMapPoint(chatId: Long, message: TdApi.Message) { val content = message.content if (content is TdApi.MessageLocation || content is MessageUserLocation) { - osmandAidlHelper.removeMapPoint(MAP_LAYER_ID, "${chatId}_${message.senderUserId}") + osmandAidlHelper.removeMapPoint(MAP_LAYER_ID, "${chatId}_${OsmandLocationUtils.getSenderMessageId(message)}") } else if (content is MessageOsmAndBotLocation) { osmandAidlHelper.removeMapPoint(MAP_LAYER_ID, "${chatId}_${content.deviceName}") } diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt index a45a08bac4..ac4dce8d43 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt @@ -39,7 +39,7 @@ class TelegramHelper private constructor() { const val MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC = 61 const val MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC = 60 * 60 * 24 - 1 // one day - const val MAX_LOCATION_MESSAGE_HISTORY_SCAN_SEC = 60 * 60 * 24 // one day + const val MAX_LOCATION_MESSAGE_HISTORY_SCAN_SEC = 7 * 60 * 60 * 24 // one day private var helper: TelegramHelper? = null @@ -146,7 +146,7 @@ class TelegramHelper private constructor() { fun getCurrentUserId() = currentUser?.id ?: -1 fun getUserMessage(user: TdApi.User) = - usersLocationMessages.values.firstOrNull { it.senderUserId == user.id } + usersLocationMessages.values.firstOrNull { OsmandLocationUtils.getSenderMessageId(it) == user.id } fun getChatMessages(chatId: Long) = usersLocationMessages.values.filter { it.chatId == chatId } @@ -348,15 +348,6 @@ class TelegramHelper private constructor() { fun isBot(userId: Int) = users[userId]?.type is TdApi.UserTypeBot - fun getSenderMessageId(message: TdApi.Message): Int { - val forwardInfo = message.forwardInfo - return if (forwardInfo != null && forwardInfo is TdApi.MessageForwardedFromUser) { - forwardInfo.senderUserId - } else { - message.senderUserId - } - } - fun startLiveMessagesUpdates(interval: Long) { stopLiveMessagesUpdates() @@ -678,18 +669,19 @@ class TelegramHelper private constructor() { lastTelegramUpdateTime = Math.max(lastTelegramUpdateTime, Math.max(message.date, message.editDate)) if (message.isAppropriate()) { log.debug("addNewMessage: ${message.id}") - val fromBot = isOsmAndBot(message.senderUserId) + val fromBot = isOsmAndBot(OsmandLocationUtils.getSenderMessageId(message)) val viaBot = isOsmAndBot(message.viaBotUserId) if (message.isOutgoing && !fromBot && !viaBot) { return } removeOldMessages(message, fromBot, viaBot) val oldMessage = usersLocationMessages.values.firstOrNull { - getSenderMessageId(it) == getSenderMessageId(message) && it.chatId == message.chatId + OsmandLocationUtils.getSenderMessageId(it) == OsmandLocationUtils.getSenderMessageId(message) && it.chatId == message.chatId && OsmandLocationUtils.getOsmAndBotDeviceName(it) == OsmandLocationUtils.getOsmAndBotDeviceName(message) } val hasNewerMessage = oldMessage != null && (Math.max(message.editDate, message.date) < Math.max(oldMessage.editDate, oldMessage.date)) if (!hasNewerMessage) { + message.content = OsmandLocationUtils.parseMessageContent(message, this) usersLocationMessages[message.id] = message } if (message.isOutgoing) { @@ -713,7 +705,7 @@ class TelegramHelper private constructor() { while (iterator.hasNext()) { val message = iterator.next().value if (newMessage.chatId == message.chatId) { - val sameSender = getSenderMessageId(newMessage) == getSenderMessageId(message) + val sameSender = OsmandLocationUtils.getSenderMessageId(newMessage) == OsmandLocationUtils.getSenderMessageId(message) val viaSameBot = newMessage.viaBotUserId == message.viaBotUserId if (fromBot || viaBot) { if ((fromBot && sameSender) || (viaBot && viaSameBot)) { @@ -1091,7 +1083,7 @@ class TelegramHelper private constructor() { } val content = content val isUserTextLocation = (content is TdApi.MessageText) && content.text.text.startsWith(USER_TEXT_LOCATION_TITLE) - val isOsmAndBot = isOsmAndBot(senderUserId) || isOsmAndBot(viaBotUserId) + val isOsmAndBot = isOsmAndBot(OsmandLocationUtils.getSenderMessageId(this)) || isOsmAndBot(viaBotUserId) if (!(isUserTextLocation || content is TdApi.MessageLocation || isOsmAndBot)) { return false } diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt index e472bc0a6f..27c5b61ae2 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt @@ -153,7 +153,7 @@ object TelegramUiHelper { chat: TdApi.Chat, message: TdApi.Message ): LocationItem? { - val user = helper.getUser(message.senderUserId) ?: return null + val user = helper.getUser(OsmandLocationUtils.getSenderMessageId(message)) ?: return null val content = OsmandLocationUtils.parseMessageContent(message, helper) return LocationItem().apply { chatId = chat.id @@ -167,7 +167,7 @@ object TelegramUiHelper { photoPath = helper.getUserPhotoPath(user) grayscalePhotoPath = helper.getUserGreyPhotoPath(user) placeholderId = R.drawable.img_user_picture - userId = message.senderUserId + userId = OsmandLocationUtils.getSenderMessageId(message) lastUpdated = OsmandLocationUtils.getLastUpdatedTime(message) } } @@ -199,7 +199,7 @@ object TelegramUiHelper { chat: TdApi.Chat, message: TdApi.Message ): ChatItem? { - val user = helper.getUser(message.senderUserId) ?: return null + val user = helper.getUser(OsmandLocationUtils.getSenderMessageId(message)) ?: return null val content = OsmandLocationUtils.parseMessageContent(message, helper) return ChatItem().apply { chatId = chat.id @@ -218,7 +218,7 @@ object TelegramUiHelper { } grayscalePhotoPath = helper.getUserGreyPhotoPath(user) placeholderId = R.drawable.img_user_picture - userId = message.senderUserId + userId = OsmandLocationUtils.getSenderMessageId(message) privateChat = helper.isPrivateChat(chat) || helper.isSecretChat(chat) chatWithBot = helper.isBot(userId) lastUpdated = OsmandLocationUtils.getLastUpdatedTime(message) diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/LiveNowTabFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/LiveNowTabFragment.kt index c0a52921a9..9adff165d9 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/LiveNowTabFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/LiveNowTabFragment.kt @@ -104,6 +104,7 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage mainView.findViewById(R.id.swipe_refresh).apply { setOnRefreshListener { app.shareLocationHelper.checkNetworkType() + app.telegramHelper.scanChatsHistory() updateList() isRefreshing = false } @@ -482,6 +483,13 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage holder.lastTelegramUpdateTime?.visibility = View.GONE } + if (settings.showGpsPoints) { + holder.receivedGpxPointsContainer?.visibility = View.VISIBLE + holder.receivedGpxPointsDescr?.text = getChatItemGpxPointsDescription(item) + } else { + holder.receivedGpxPointsContainer?.visibility = View.GONE + } + if (item is ChatItem && holder is ChatViewHolder) { val nextIsLocation = !lastItem && (items[position + 1] is LocationItem || !sortByGroup) val chatId = item.chatId @@ -497,6 +505,13 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage holder.groupDescrContainer?.visibility = View.GONE } + if (settings.showGpsPoints) { + holder.receivedGpxPointsContainer?.visibility = View.VISIBLE + holder.receivedGpxPointsDescr?.text = getChatItemGpxPointsDescription(item) + } else { + holder.receivedGpxPointsContainer?.visibility = View.GONE + } + holder.description?.text = getChatItemDescription(item) holder.imageButton?.visibility = View.GONE holder.showOnMapRow?.setOnClickListener { showPopupMenu(holder, chatId) } @@ -505,6 +520,12 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage holder.topDivider?.visibility = if (!sortByGroup && position != 0) View.GONE else View.VISIBLE } else if (item is LocationItem && holder is ContactViewHolder) { holder.description?.text = OsmandFormatter.getListItemLiveTimeDescr(app, item.lastUpdated, lastResponseStr) + if (settings.showGpsPoints) { + holder.receivedGpxPointsContainer?.visibility = View.VISIBLE + holder.receivedGpxPointsDescr?.text = getChatItemGpxPointsDescription(item) + } else { + holder.receivedGpxPointsContainer?.visibility = View.GONE + } } } @@ -533,6 +554,51 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage } } + private fun getChatItemGpxPointsDescription(item: ListItem): String { + return when { + item is ChatItem && item.chatWithBot -> { + if (settings.liveNowSortType.isSortByGroup()) { + getString(R.string.shared_string_bot) + } else { + val deviceName = if(item.chatWithBot) item.name else "" + val start = System.currentTimeMillis() - settings.locHistoryTime * 1000 + val end = System.currentTimeMillis() + val userLocations = app.locationMessages.getIngoingUserLocationsInChat(item.userId, item.chatId,deviceName,start, end) + var points = 0 + userLocations?.getUniqueSegments()?.forEach { points += it.points.size } + getString(R.string.received_gps_points, points) + } + } + item is ChatItem && item.privateChat -> { + val deviceName = if(item.chatWithBot) item.name else "" + val start = System.currentTimeMillis() - settings.locHistoryTime * 1000 + val end = System.currentTimeMillis() + val userLocations = app.locationMessages.getIngoingUserLocationsInChat(item.userId, item.chatId,deviceName,start, end) + var points = 0 + userLocations?.getUniqueSegments()?.forEach { points += it.points.size } + getString(R.string.received_gps_points, points) + } + else -> { + if (!settings.liveNowSortType.isSortByGroup()&&item is ChatItem) { + val deviceName = if(item.chatWithBot) item.name else "" + val start = System.currentTimeMillis() - settings.locHistoryTime * 1000 + val end = System.currentTimeMillis() + val userLocations = app.locationMessages.getIngoingUserLocationsInChat(item.userId, item.chatId,deviceName,start, end) + var points = 0 + userLocations?.getUniqueSegments()?.forEach { points += it.points.size } + getString(R.string.received_gps_points, points) + } else { + val start = System.currentTimeMillis() - settings.locHistoryTime * 1000 + val end = System.currentTimeMillis() + val userLocations = app.locationMessages.getIngoingUserLocationsInChat(item.userId, item.chatId,"",start, end) + var points = 0 + userLocations?.getUniqueSegments()?.forEach { points += it.points.size } + getString(R.string.received_gps_points, points) + } + } + } + } + private fun showPopupMenu(holder: ChatViewHolder, chatId: Long) { val ctx = holder.itemView.context @@ -584,6 +650,8 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage val directionIcon: ImageView? = view.findViewById(R.id.direction_icon) val distanceText: TextView? = view.findViewById(R.id.distance_text) val description: TextView? = view.findViewById(R.id.description) + val receivedGpxPointsContainer: View? = view.findViewById(R.id.received_gps_points_container) + val receivedGpxPointsDescr: TextView? = view.findViewById(R.id.received_gps_points_description) val bottomShadow: View? = view.findViewById(R.id.bottom_shadow) val lastTelegramUpdateTime: TextView? = view.findViewById(R.id.last_telegram_update_time) diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt index 94486cef03..cb22f4e849 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt @@ -13,15 +13,21 @@ import android.support.v4.content.ContextCompat import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.RecyclerView import android.text.SpannableString +import android.text.SpannableStringBuilder import android.text.style.ForegroundColorSpan import android.view.* import android.view.animation.LinearInterpolator import android.widget.* -import net.osmand.telegram.* +import net.osmand.telegram.ADDITIONAL_ACTIVE_TIME_VALUES_SEC +import net.osmand.telegram.R +import net.osmand.telegram.SHARE_TYPE_MAP +import net.osmand.telegram.TelegramApplication +import net.osmand.telegram.helpers.FontCache import net.osmand.telegram.helpers.LocationMessages import net.osmand.telegram.helpers.TelegramHelper import net.osmand.telegram.helpers.TelegramHelper.TelegramListener import net.osmand.telegram.helpers.TelegramUiHelper +import net.osmand.telegram.ui.views.CustomTypefaceSpan import net.osmand.telegram.utils.AndroidUtils import net.osmand.telegram.utils.OsmandFormatter import org.drinkless.td.libcore.telegram.TdApi @@ -695,45 +701,43 @@ class MyLocationTabFragment : Fragment(), TelegramListener { } } - holder.stopSharingDescr?.apply { - visibility = getStopSharingVisibility(expiresIn) - text = getText(R.string.expire_at) - } - - holder.stopSharingFirstPart?.apply { - visibility = getStopSharingVisibility(expiresIn) - text = OsmandFormatter.getFormattedTime(expiresIn * 1000) - } - - holder.stopSharingSecondPart?.apply { - visibility = getStopSharingVisibility(expiresIn) - text = "(${getString( - R.string.in_time, - OsmandFormatter.getFormattedDuration(context!!, expiresIn, true) - )})" - } - holder.gpsPointsCollected?.apply { - if (shareInfo != null) { - text = " ${shareInfo.sentMessages}" + holder.sharingExpiresLine?.apply { + visibility = if (expiresIn > 0) View.VISIBLE else View.GONE + val description = SpannableStringBuilder(getText(R.string.expire_at)) + val typeface = FontCache.getRobotoMonoBold(app) + val start = description.length + description.append(" ${OsmandFormatter.getFormattedTime(expiresIn * 1000)} ") + if (typeface != null) { + description.setSpan(CustomTypefaceSpan(typeface), start, description.length, 0) } + description.setSpan(ForegroundColorSpan(ContextCompat.getColor(app, R.color.primary_text_light)), start, description.length, 0) + description.append((getString(R.string.in_time, OsmandFormatter.getFormattedDuration(context!!, expiresIn, true)))) + text = description } - holder.gpsPointsSent?.apply { + + holder.gpsPointsLine?.apply { + visibility = if (app.settings.showGpsPoints && shareInfo != null) View.VISIBLE else View.GONE if (shareInfo != null) { - val bufferedPoints = - if (app.settings.shareTypeValue == SHARE_TYPE_MAP_AND_TEXT || app.settings.shareTypeValue == SHARE_TYPE_TEXT) { - shareInfo.pendingTdLibText + app.locationMessages.getBufferedMessagesCountForChat(shareInfo.chatId, LocationMessages.TYPE_TEXT) - } else { - shareInfo.pendingTdLibMap + app.locationMessages.getBufferedMessagesCountForChat(shareInfo.chatId, LocationMessages.TYPE_MAP) - } - text = getString(R.string.gps_points_in_buffer, bufferedPoints) + val description = SpannableStringBuilder(getText(R.string.gps_points)) + val typeface = FontCache.getRobotoMonoBold(app) + val bufferedPoints = if (app.settings.shareTypeValue == SHARE_TYPE_MAP) { + shareInfo.pendingTdLibMap + app.locationMessages.getBufferedMessagesCountForChat(shareInfo.chatId, LocationMessages.TYPE_MAP) + } else { + shareInfo.pendingTdLibText + app.locationMessages.getBufferedMessagesCountForChat(shareInfo.chatId, LocationMessages.TYPE_TEXT) + } + val start = description.length + description.append(" ${shareInfo.sentMessages} ") + if (typeface != null) { + description.setSpan(CustomTypefaceSpan(typeface), start, description.length, 0) + } + description.setSpan(ForegroundColorSpan(ContextCompat.getColor(app, R.color.primary_text_light)), start, description.length, 0) + description.append(getString(R.string.gps_points_in_buffer, bufferedPoints)) + text = description } } } } - private fun getStopSharingVisibility(expiresIn: Long) = - if (expiresIn > 0) View.VISIBLE else View.GONE - private fun removeItem(chat: TdApi.Object) { items.remove(chat) if (items.isEmpty()) { @@ -762,11 +766,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener { inner class SharingChatViewHolder(val view: View) : BaseViewHolder(view) { val descriptionDuration: TextView? = view.findViewById(R.id.duration) val switcher: Switch? = view.findViewById(R.id.switcher) - val stopSharingDescr: TextView? = view.findViewById(R.id.stop_in) - val stopSharingFirstPart: TextView? = view.findViewById(R.id.ending_in_first_part) - val stopSharingSecondPart: TextView? = view.findViewById(R.id.ending_in_second_part) - val gpsPointsCollected: TextView? = view.findViewById(R.id.gps_points_collected) - val gpsPointsSent: TextView? = view.findViewById(R.id.gps_points_in_buffer_txt) + val sharingExpiresLine: TextView? = view.findViewById(R.id.expires_line) + val gpsPointsLine: TextView? = view.findViewById(R.id.gps_points_line) } } diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/SettingsDialogFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/SettingsDialogFragment.kt index 44db164777..cb4ca435c2 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/SettingsDialogFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/SettingsDialogFragment.kt @@ -75,6 +75,22 @@ class SettingsDialogFragment : BaseDialogFragment() { } } + container = mainView.findViewById(R.id.gps_points_container) + inflater.inflate(R.layout.item_with_descr_and_right_switch, container, false).apply { + findViewById(R.id.icon).setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_connect)) + findViewById(R.id.title).text = getText(R.string.show_gps_points) + findViewById(R.id.description).text = getText(R.string.show_gps_points_descr) + val switcher = findViewById(R.id.switcher).apply { + isChecked = app.settings.showGpsPoints + } + setOnClickListener { + val checked = !app.settings.showGpsPoints + app.settings.showGpsPoints = checked + switcher.isChecked = checked + } + container.addView(this) + } + shareAsDescription = mainView.findViewById(R.id.share_as_description).apply { text = getText(R.string.share_location_as_description) setOnClickListener { diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/TimelineTabFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/TimelineTabFragment.kt index bc7f48dd80..6069f5b5a6 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/TimelineTabFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/TimelineTabFragment.kt @@ -239,8 +239,9 @@ class TimelineTabFragment : Fragment() { holder.locationAndDescrContainer?.visibility = View.GONE holder.distanceAndPointsContainer?.visibility = View.VISIBLE holder.distanceImage?.setImageDrawable(app.uiUtils.getThemedIcon(R.drawable.ic_action_distance_16dp)) - val point = if (groupDescrRowVisible) " • " else "" - holder.distanceAndPointsTitle?.text = "$distance (${getString(R.string.points_size, trackData.points)}) $point " + val bullet = if (groupDescrRowVisible) " • " else "" + val points = if (app.settings.showGpsPoints) "(${getString(R.string.points_size, trackData.points)})" else "" + holder.distanceAndPointsTitle?.text = "$distance $points $bullet " holder.userRow?.setOnClickListener { childFragmentManager.also { UserGpxInfoFragment.showInstance(it, item.userId, item.chatId, userLocations.deviceName ,trackData.minTime, trackData.maxTime) @@ -263,7 +264,7 @@ class TimelineTabFragment : Fragment() { if (uiTrackData.minTime == 0L) { uiTrackData.minTime = it.minTime } - uiTrackData.dist += it.distance.toFloat(); + uiTrackData.dist += it.distance.toFloat() uiTrackData.points += it.points.size uiTrackData.maxTime = it.maxTime } diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/views/CustomTypefaceSpan.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/views/CustomTypefaceSpan.kt new file mode 100644 index 0000000000..6a22646785 --- /dev/null +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/views/CustomTypefaceSpan.kt @@ -0,0 +1,21 @@ +package net.osmand.telegram.ui.views + +import android.graphics.Typeface +import android.text.TextPaint +import android.text.style.MetricAffectingSpan + +class CustomTypefaceSpan(val font: Typeface) : MetricAffectingSpan() { + + override fun updateMeasureState(textPaint: TextPaint) = update(textPaint) + + + override fun updateDrawState(textPaint: TextPaint) = update(textPaint) + + private fun update(textPaint: TextPaint) { + textPaint.apply { + val old = typeface + val oldStyle = old?.style ?: 0 + typeface = Typeface.create(font, oldStyle) + } + } +} \ No newline at end of file diff --git a/OsmAnd-telegram/src/net/osmand/telegram/utils/OsmandLocationUtils.kt b/OsmAnd-telegram/src/net/osmand/telegram/utils/OsmandLocationUtils.kt index 8a086b31d0..eaeb328fce 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/utils/OsmandLocationUtils.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/utils/OsmandLocationUtils.kt @@ -61,10 +61,11 @@ object OsmandLocationUtils { if (message.replyMarkup is TdApi.ReplyMarkupInlineKeyboard) { val replyMarkup = message.replyMarkup as TdApi.ReplyMarkupInlineKeyboard try { - if (replyMarkup.rows[0].size > 1) { - deviceName = replyMarkup.rows[0][1].text.split("\\s".toRegex())[1] - } else if (message.content is TdApi.MessageText) { - deviceName = (message.content as TdApi.MessageText).text.text.lines().firstOrNull()?.removePrefix(DEVICE_PREFIX) ?: "" + val content = message.content + when { + replyMarkup.rows[0].size > 1 -> deviceName = replyMarkup.rows[0][1].text.split("\\s".toRegex())[1] + content is TdApi.MessageText -> deviceName = content.text.text.lines().firstOrNull()?.removePrefix(DEVICE_PREFIX) ?: "" + content is MessageOsmAndBotLocation -> deviceName = content.deviceName } } catch (e: Exception) { @@ -89,13 +90,22 @@ object OsmandLocationUtils { return res } + fun getSenderMessageId(message: TdApi.Message): Int { + val forwardInfo = message.forwardInfo + return if (forwardInfo != null && forwardInfo is TdApi.MessageForwardedFromUser) { + forwardInfo.senderUserId + } else { + message.senderUserId + } + } + fun parseMessage(message: TdApi.Message, helper: TelegramHelper, previousMessageLatLon: LatLon?): LocationMessage? { val parsedContent = parseMessageContent(message, helper) - return createLocationMessage(message, helper, parsedContent, previousMessageLatLon) + return createLocationMessage(message, parsedContent, previousMessageLatLon) } fun parseMessageContent(message: TdApi.Message, helper: TelegramHelper): MessageLocation? { - val senderUserId = helper.getSenderMessageId(message) + val senderUserId = getSenderMessageId(message) val fromBot = helper.isOsmAndBot(senderUserId) val viaBot = helper.isOsmAndBot(message.viaBotUserId) return when (message.content) { @@ -106,11 +116,11 @@ object OsmandLocationUtils { } } - fun createLocationMessage(message: TdApi.Message, helper: TelegramHelper, content:MessageLocation?, previousMessageLatLon: LatLon?):LocationMessage?{ + fun createLocationMessage(message: TdApi.Message, content:MessageLocation?, previousMessageLatLon: LatLon?):LocationMessage?{ if (content == null) { return null } - val senderUserId = helper.getSenderMessageId(message) + val senderUserId = getSenderMessageId(message) val messageType = getMessageType(message) val distanceFromPrev = if (previousMessageLatLon != null) MapUtils.getDistance(previousMessageLatLon, content.lat, content.lon) else 0.0 val deviceName = if (content is MessageOsmAndBotLocation) content.deviceName else ""