diff --git a/OsmAnd-telegram/res/layout/fragment_timeline_tab.xml b/OsmAnd-telegram/res/layout/fragment_timeline_tab.xml index 957b6db002..64d501740f 100644 --- a/OsmAnd-telegram/res/layout/fragment_timeline_tab.xml +++ b/OsmAnd-telegram/res/layout/fragment_timeline_tab.xml @@ -96,7 +96,7 @@ android:layout_height="1dp" android:background="@color/app_bar_divider" /> - - - - - - + diff --git a/OsmAnd-telegram/res/values/strings.xml b/OsmAnd-telegram/res/values/strings.xml index 805b3f114c..eaa5488040 100644 --- a/OsmAnd-telegram/res/values/strings.xml +++ b/OsmAnd-telegram/res/values/strings.xml @@ -1,4 +1,6 @@ + %1$d points + Date Collected Gps points Sent diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt index c934a6d201..a0a168c2c1 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt @@ -276,10 +276,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis override fun onReceiveChatLocationMessages(chatId: Long, vararg messages: TdApi.Message) { app().showLocationHelper.startShowMessagesTask(chatId, *messages) messages.forEach { - val locationMessage = OsmandLocationUtils.parseMessage(it, app().telegramHelper) - if (locationMessage != null) { - app().locationMessages.addLocationMessage(locationMessage) - } + app().locationMessages.addNewLocationMessage(it) } } @@ -296,10 +293,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis app().settings.updateShareInfo(it) app().shareLocationHelper.checkAndSendBufferMessagesToChat(it.chatId) if (it.sendingState == null && (it.content is TdApi.MessageLocation || it.content is TdApi.MessageText)) { - val locationMessage = OsmandLocationUtils.parseMessage(it, app().telegramHelper) - if (locationMessage != null) { - app().locationMessages.addLocationMessage(locationMessage) - } + app().locationMessages.addNewLocationMessage(it) } } } diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt index 202c745585..ea5e870fbb 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt @@ -245,31 +245,31 @@ class TelegramSettings(private val app: TelegramApplication) { } fun updateShareInfo(message: TdApi.Message) { - val shareChatInfo = shareChatsInfo[message.chatId] + val shareInfo = shareChatsInfo[message.chatId] val content = message.content - if (shareChatInfo != null) { + if (shareInfo != null) { when (content) { is TdApi.MessageLocation -> { val state = message.sendingState if (state != null) { if (state.constructor == TdApi.MessageSendingStatePending.CONSTRUCTOR) { - shareChatInfo.pendingMapMessage = true + shareInfo.pendingMapMessage = true log.debug("updateShareInfo MAP ${message.id} MessageSendingStatePending") - shareChatInfo.oldMapMessageId = message.id + shareInfo.oldMapMessageId = message.id } else if (state.constructor == TdApi.MessageSendingStateFailed.CONSTRUCTOR) { - shareChatInfo.hasSharingError = true - shareChatInfo.pendingMapMessage = false + shareInfo.hasSharingError = true + shareInfo.pendingMapMessage = false log.debug("updateShareInfo MAP ${message.id} MessageSendingStateFailed") } } else { - log.debug("updateShareInfo MAP ${message.id} SUCCESS") - shareChatInfo.currentMapMessageId = message.id - shareChatInfo.pendingMapMessage = false - shareChatInfo.pendingTdLib-- - shareChatInfo.lastSuccessfulSendTimeMs = Math.max(message.editDate, message.date) * 1000L + shareInfo.currentMapMessageId = message.id + shareInfo.pendingMapMessage = false + shareInfo.pendingTdLib-- + shareInfo.lastSuccessfulSendTimeMs = Math.max(message.editDate, message.date) * 1000L if (shareTypeValue == SHARE_TYPE_MAP) { - shareChatInfo.sentMessages++ + shareInfo.sentMessages++ } + log.debug("updateShareInfo MAP ${message.id} SUCCESS pendingTdLib: ${shareInfo.pendingTdLib}") } } is TdApi.MessageText -> { @@ -277,21 +277,21 @@ class TelegramSettings(private val app: TelegramApplication) { if (state != null) { if (state.constructor == TdApi.MessageSendingStatePending.CONSTRUCTOR) { log.debug("updateShareInfo TEXT ${message.id} MessageSendingStatePending") - shareChatInfo.pendingTextMessage = true - shareChatInfo.oldTextMessageId = message.id + shareInfo.pendingTextMessage = true + shareInfo.oldTextMessageId = message.id } else if (state.constructor == TdApi.MessageSendingStateFailed.CONSTRUCTOR) { log.debug("updateShareInfo TEXT ${message.id} MessageSendingStateFailed") - shareChatInfo.hasSharingError = true - shareChatInfo.pendingTextMessage = false + shareInfo.hasSharingError = true + shareInfo.pendingTextMessage = false } } else { - log.debug("updateShareInfo TEXT ${message.id} SUCCESS") - shareChatInfo.currentTextMessageId = message.id - shareChatInfo.updateTextMessageId++ - shareChatInfo.pendingTextMessage = false - shareChatInfo.pendingTdLib-- - shareChatInfo.sentMessages++ - shareChatInfo.lastSuccessfulSendTimeMs = Math.max(message.editDate, message.date) * 1000L + shareInfo.currentTextMessageId = message.id + shareInfo.updateTextMessageId++ + shareInfo.pendingTextMessage = false + shareInfo.pendingTdLib-- + shareInfo.sentMessages++ + shareInfo.lastSuccessfulSendTimeMs = Math.max(message.editDate, message.date) * 1000L + log.debug("updateShareInfo TEXT ${message.id} SUCCESS pendingTdLib: ${shareInfo.pendingTdLib}") } } } @@ -582,6 +582,7 @@ class TelegramSettings(private val app: TelegramApplication) { obj.put(ShareChatInfo.PENDING_MAP_MESSAGE_KEY, chatInfo.pendingMapMessage) obj.put(ShareChatInfo.COLLECTED_MESSAGES_KEY, chatInfo.collectedMessages) obj.put(ShareChatInfo.SENT_MESSAGES_KEY, chatInfo.sentMessages) + obj.put(ShareChatInfo.PENDING_TDLIB_KEY, chatInfo.pendingTdLib) jArray.put(obj) } jArray @@ -612,6 +613,7 @@ class TelegramSettings(private val app: TelegramApplication) { pendingMapMessage = obj.optBoolean(ShareChatInfo.PENDING_MAP_MESSAGE_KEY) collectedMessages = obj.optInt(ShareChatInfo.COLLECTED_MESSAGES_KEY) sentMessages = obj.optInt(ShareChatInfo.SENT_MESSAGES_KEY) + pendingTdLib = obj.optInt(ShareChatInfo.PENDING_TDLIB_KEY) } shareChatsInfo[shareInfo.chatId] = shareInfo } @@ -942,6 +944,7 @@ class TelegramSettings(private val app: TelegramApplication) { internal const val PENDING_MAP_MESSAGE_KEY = "pendingMapMessage" internal const val COLLECTED_MESSAGES_KEY = "collectedMessages" internal const val SENT_MESSAGES_KEY = "sentMessages" + internal const val PENDING_TDLIB_KEY = "sentMessages" } } } \ No newline at end of file diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt index 9ed9af7d13..591629780b 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt @@ -6,6 +6,8 @@ import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteOpenHelper import net.osmand.PlatformUtil import net.osmand.telegram.TelegramApplication +import net.osmand.telegram.utils.OsmandLocationUtils +import org.drinkless.td.libcore.telegram.TdApi class LocationMessages(val app: TelegramApplication) { @@ -14,6 +16,8 @@ class LocationMessages(val app: TelegramApplication) { // todo - bufferedMessages is for prepared/pending messages only. On app start we read prepared/pending messages to bufferedMessages. After status changed to sent/error - remove message from buffered. private var bufferedMessages = emptyList() + private var lastMessages = emptyList() + private val dbHelper: SQLiteHelper init { @@ -21,12 +25,11 @@ class LocationMessages(val app: TelegramApplication) { readBufferedMessages() } - fun getPreparedMessages(): List { + fun getBufferedMessages(): List { return bufferedMessages.sortedBy { it.time } } - fun getPreparedMessagesForChat(chatId: Long): List { - log.debug("getPreparedMessagesForChat chatId") + fun getBufferedMessagesForChat(chatId: Long): List { return bufferedMessages.filter { it.chatId==chatId }.sortedBy { it.time } } @@ -35,8 +38,8 @@ class LocationMessages(val app: TelegramApplication) { return dbHelper.getIngoingMessages(currentUserId, start, end) } - fun getIngoingMessagesForUser(userId: Int, chatId: Long, start: Long, end: Long): List { - return dbHelper.getIngoingMessagesForUser(userId, chatId, start, end) + fun getMessagesForUserInChat(userId: Int, chatId: Long, start: Long, end: Long): List { + return dbHelper.getMessagesForUserInChat(userId, chatId, start, end) } fun getMessagesForUser(userId: Int, start: Long, end: Long): List { @@ -51,9 +54,19 @@ class LocationMessages(val app: TelegramApplication) { dbHelper.addBufferedMessage(message) } - fun addLocationMessage(message: LocationMessage) { - log.debug("addIngoingMessage $message") - dbHelper.addLocationMessage(message) + fun addNewLocationMessage(message: TdApi.Message) { + log.debug("addNewLocationMessage ${message.id}") + val type = OsmandLocationUtils.getMessageType(message, app.telegramHelper) + + val previousMessage = lastMessages.firstOrNull { it.chatId == message.chatId && it.userId == message.senderUserId && it.type == type } + val locationMessage = OsmandLocationUtils.parseMessage(message, app.telegramHelper, previousMessage) + if (locationMessage != null) { + dbHelper.addLocationMessage(locationMessage) + val messages = mutableListOf(*this.lastMessages.toTypedArray()) + messages.remove(previousMessage) + messages.add(locationMessage) + this.lastMessages = messages + } } fun clearBufferedMessages() { @@ -74,6 +87,10 @@ class LocationMessages(val app: TelegramApplication) { this.bufferedMessages = dbHelper.getBufferedMessages() } + private fun readLastMessages() { + this.lastMessages = dbHelper.getLastMessages() + } + private class SQLiteHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { @@ -98,7 +115,7 @@ class LocationMessages(val app: TelegramApplication) { internal fun addLocationMessage(message: LocationMessage) { writableDatabase?.execSQL(TIMELINE_TABLE_INSERT, arrayOf(message.userId, message.chatId, message.lat, message.lon, message.altitude, message.speed, - message.hdop, message.bearing, message.time, message.type)) + message.hdop, message.bearing, message.time, message.type, message.messageId, message.distanceFromPrev)) } internal fun getMessagesForUser(userId: Int, start: Long, end: Long): List { @@ -116,10 +133,23 @@ class LocationMessages(val app: TelegramApplication) { return res } + internal fun getPreviousMessage(userId: Int, chatId: Long): LocationMessage? { + var res:LocationMessage? = null + readableDatabase?.rawQuery( + "$TIMELINE_TABLE_SELECT WHERE $COL_USER_ID = ? AND $COL_CHAT_ID = ? ORDER BY $COL_TIME DESC LIMIT 1", + arrayOf(userId.toString(), chatId.toString()))?.apply { + if (moveToFirst()) { + res = readLocationMessage(this@apply) + } + close() + } + return res + } + internal fun getIngoingMessages(currentUserId: Int, start: Long, end: Long): List { val res = arrayListOf() readableDatabase?.rawQuery( - "$TIMELINE_TABLE_SELECT WHERE $COL_USER_ID != ? AND $COL_CHAT_ID = ? AND $COL_TIME BETWEEN $start AND $end ORDER BY $COL_TIME ASC ", + "$TIMELINE_TABLE_SELECT WHERE $COL_USER_ID != ? AND $COL_TIME BETWEEN $start AND $end ORDER BY $COL_USER_ID ASC, $COL_CHAT_ID ASC, $COL_TIME ASC ", arrayOf(currentUserId.toString()))?.apply { if (moveToFirst()) { do { @@ -131,11 +161,11 @@ class LocationMessages(val app: TelegramApplication) { return res } - internal fun getIngoingMessagesForUser(userId: Int, chatId: Long, start: Long, end: Long): List { + internal fun getMessagesForUserInChat(userId: Int, chatId: Long, start: Long, end: Long): List { val res = arrayListOf() readableDatabase?.rawQuery( "$TIMELINE_TABLE_SELECT WHERE $COL_USER_ID = ? AND $COL_CHAT_ID = ? AND $COL_TIME BETWEEN $start AND $end ORDER BY $COL_TIME ASC ", - arrayOf(userId.toString(), chatId.toString(), start.toString(), end.toString()))?.apply { + arrayOf(userId.toString(), chatId.toString()))?.apply { if (moveToFirst()) { do { res.add(readLocationMessage(this@apply)) @@ -159,6 +189,19 @@ class LocationMessages(val app: TelegramApplication) { return res } + internal fun getLastMessages(): List { + val res = arrayListOf() + readableDatabase?.rawQuery(TIMELINE_TABLE_SELECT, null)?.apply { + if (moveToFirst()) { + do { + res.add(readLocationMessage(this@apply)) + } while (moveToNext()) + } + close() + } + return res + } + internal fun readLocationMessage(cursor: Cursor): LocationMessage { val userId = cursor.getInt(0) val chatId = cursor.getLong(1) @@ -170,8 +213,10 @@ class LocationMessages(val app: TelegramApplication) { val bearing = cursor.getDouble(7) val date = cursor.getLong(8) val type = cursor.getInt(9) + val messageId = cursor.getLong(10) + val distanceFromPrev = cursor.getDouble(11) - return LocationMessage(userId, chatId, lat, lon, altitude, speed, hdop, bearing, date, type) + return LocationMessage(userId, chatId, lat, lon, altitude, speed, hdop, bearing, date, type, messageId, distanceFromPrev) } internal fun readBufferMessage(cursor: Cursor): BufferMessage { @@ -213,7 +258,7 @@ class LocationMessages(val app: TelegramApplication) { companion object { private const val DATABASE_NAME = "location_messages" - private const val DATABASE_VERSION = 4 + private const val DATABASE_VERSION = 5 private const val TIMELINE_TABLE_NAME = "timeline" private const val BUFFER_TABLE_NAME = "buffer" @@ -229,18 +274,19 @@ class LocationMessages(val app: TelegramApplication) { private const val COL_BEARING = "bearing" private const val COL_TYPE = "type" // 0 = user map message, 1 = user text message, 2 = bot map message, 3 = bot text message private const val COL_MESSAGE_ID = "message_id" + private const val COL_DISTANCE_FROM_PREV = "distance_from_prev" private const val DATE_INDEX = "date_index" // Timeline messages table private const val TIMELINE_TABLE_INSERT = - ("INSERT INTO $TIMELINE_TABLE_NAME ($COL_USER_ID, $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_TIME, $COL_TYPE, $COL_MESSAGE_ID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") + ("INSERT INTO $TIMELINE_TABLE_NAME ($COL_USER_ID, $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_TIME, $COL_TYPE, $COL_MESSAGE_ID, $COL_DISTANCE_FROM_PREV) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") private const val TIMELINE_TABLE_CREATE = - ("CREATE TABLE IF NOT EXISTS $TIMELINE_TABLE_NAME ($COL_USER_ID long, $COL_CHAT_ID long,$COL_LAT double, $COL_LON double, $COL_ALTITUDE double, $COL_SPEED float, $COL_HDOP double, $COL_BEARING double, $COL_TIME long, $COL_TYPE int, $COL_MESSAGE_ID long )") + ("CREATE TABLE IF NOT EXISTS $TIMELINE_TABLE_NAME ($COL_USER_ID long, $COL_CHAT_ID long,$COL_LAT double, $COL_LON double, $COL_ALTITUDE double, $COL_SPEED float, $COL_HDOP double, $COL_BEARING double, $COL_TIME long, $COL_TYPE int, $COL_MESSAGE_ID long, $COL_DISTANCE_FROM_PREV double )") private const val TIMELINE_TABLE_SELECT = - "SELECT $COL_USER_ID, $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_TIME, $COL_TYPE, $COL_MESSAGE_ID FROM $TIMELINE_TABLE_NAME" + "SELECT $COL_USER_ID, $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_TIME, $COL_TYPE, $COL_MESSAGE_ID, $COL_DISTANCE_FROM_PREV FROM $TIMELINE_TABLE_NAME" private const val TIMELINE_TABLE_CLEAR = "DELETE FROM $TIMELINE_TABLE_NAME" @@ -274,7 +320,9 @@ class LocationMessages(val app: TelegramApplication) { val hdop: Double, val bearing: Double, val time: Long, - val type: Int) + val type: Int, + val messageId: Long, + val distanceFromPrev: Double) data class BufferMessage ( val chatId: Long, diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShareLocationHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShareLocationHelper.kt index 16723a9102..0d1dbc0796 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShareLocationHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShareLocationHelper.kt @@ -96,10 +96,9 @@ class ShareLocationHelper(private val app: TelegramApplication) { } fun checkAndSendBufferMessagesToChat(chatId: Long) { - log.debug("checkAndSendBufferMessagesToChat $chatId") val shareInfo = app.settings.getChatsShareInfo()[chatId] if (shareInfo != null && shareInfo.pendingTdLib < 10) { - app.locationMessages.getPreparedMessagesForChat(shareInfo.chatId).forEach { + app.locationMessages.getBufferedMessagesForChat(shareInfo.chatId).forEach { if (it.type == LocationMessages.TYPE_USER_TEXT && !shareInfo.pendingTextMessage && shareInfo.currentTextMessageId != -1L) { app.telegramHelper.editTextLocation(shareInfo, it) app.locationMessages.removeBufferedMessage(it) @@ -169,7 +168,7 @@ class ShareLocationHelper(private val app: TelegramApplication) { log.debug("checkAndSendBufferMessages") app.settings.getChatsShareInfo().forEach loop@{ (chatId, shareInfo) -> if (shareInfo.pendingTdLib < 10) { - app.locationMessages.getPreparedMessagesForChat(chatId).forEach { + app.locationMessages.getBufferedMessagesForChat(chatId).forEach { if (it.type == LocationMessages.TYPE_USER_TEXT && !shareInfo.pendingTextMessage && shareInfo.currentTextMessageId != -1L) { app.telegramHelper.editTextLocation(shareInfo, it) app.locationMessages.removeBufferedMessage(it) diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShowLocationHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShowLocationHelper.kt index ee3d12d90b..44befe2886 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShowLocationHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShowLocationHelper.kt @@ -11,7 +11,7 @@ import net.osmand.telegram.TelegramApplication import net.osmand.telegram.helpers.TelegramUiHelper.ListItem import net.osmand.telegram.utils.AndroidUtils import net.osmand.telegram.utils.OsmandLocationUtils -import net.osmand.telegram.utils.OsmandLocationUtils.MessageUserTextLocation +import net.osmand.telegram.utils.OsmandLocationUtils.MessageUserLocation import net.osmand.telegram.utils.OsmandLocationUtils.MessageOsmAndBotLocation import org.drinkless.td.libcore.telegram.TdApi import java.io.File @@ -81,7 +81,7 @@ class ShowLocationHelper(private val app: TelegramApplication) { val content = message.content val date = OsmandLocationUtils.getLastUpdatedTime(message) val stale = System.currentTimeMillis() / 1000 - date > app.settings.staleLocTime - if (chatTitle != null && (content is TdApi.MessageLocation || (content is MessageUserTextLocation && content.isValid()))) { + if (chatTitle != null && (content is TdApi.MessageLocation || (content is MessageUserLocation && content.isValid()))) { var userName = "" var photoPath: String? = null val user = telegramHelper.getUser(message.senderUserId) @@ -106,7 +106,7 @@ class ShowLocationHelper(private val app: TelegramApplication) { val params = generatePointParams(photoPath, stale) val aLatLon = when (content) { is TdApi.MessageLocation -> ALatLon(content.location.latitude, content.location.longitude) - is MessageUserTextLocation -> ALatLon(content.lat, content.lon) + is MessageUserLocation -> ALatLon(content.lat, content.lon) else -> null } if (aLatLon != null) { @@ -251,7 +251,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 MessageUserTextLocation) { + if (content is TdApi.MessageLocation || content is MessageUserLocation) { osmandAidlHelper.removeMapPoint(MAP_LAYER_ID, "${chatId}_${message.senderUserId}") } else if (content is MessageOsmAndBotLocation) { osmandAidlHelper.removeMapPoint(MAP_LAYER_ID, "${chatId}_${content.name}") diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt index f82107d977..8e37e0ed1d 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt @@ -9,7 +9,7 @@ import net.osmand.telegram.utils.GRAYSCALE_PHOTOS_EXT import net.osmand.telegram.utils.OsmandLocationUtils import net.osmand.telegram.utils.OsmandLocationUtils.DEVICE_PREFIX import net.osmand.telegram.utils.OsmandLocationUtils.MessageOsmAndBotLocation -import net.osmand.telegram.utils.OsmandLocationUtils.MessageUserTextLocation +import net.osmand.telegram.utils.OsmandLocationUtils.MessageUserLocation import net.osmand.telegram.utils.OsmandLocationUtils.USER_TEXT_LOCATION_TITLE import net.osmand.telegram.utils.OsmandLocationUtils.getLastUpdatedTime import net.osmand.telegram.utils.OsmandLocationUtils.parseOsmAndBotLocation @@ -396,7 +396,7 @@ class TelegramHelper private constructor() { private fun isUserLocationMessage(message: TdApi.Message): Boolean { val cont = message.content - return (cont is MessageUserTextLocation || cont is TdApi.MessageLocation) + return (cont is MessageUserLocation || cont is TdApi.MessageLocation) } private fun hasLocalUserPhoto(user: TdApi.User): Boolean { @@ -688,10 +688,6 @@ class TelegramHelper private constructor() { } } - fun loadMessage(chatId: Long, messageId: Long) { - requestMessage(chatId, messageId, this@TelegramHelper::addNewMessage) - } - private fun requestMessage(chatId: Long, messageId: Long, onComplete: (TdApi.Message) -> Unit) { client?.send(TdApi.GetMessage(chatId, messageId)) { obj -> if (obj is TdApi.Message) { @@ -703,6 +699,9 @@ class TelegramHelper private constructor() { private fun addNewMessage(message: TdApi.Message) { lastTelegramUpdateTime = Math.max(lastTelegramUpdateTime, Math.max(message.date, message.editDate)) if (message.isAppropriate()) { + if (message.isOutgoing) { + return + } log.debug("addNewMessage: ${message.id}") val fromBot = isOsmAndBot(message.senderUserId) val viaBot = isOsmAndBot(message.viaBotUserId) @@ -716,21 +715,15 @@ class TelegramHelper private constructor() { } else if (oldContent is TdApi.MessageLocation && (fromBot || viaBot)) { message.content = parseOsmAndBotLocation(message) } - if (message.isOutgoing) { - outgoingMessagesListeners.forEach { - it.onUpdateMessages(listOf(message)) - } - } else { - removeOldMessages(message, fromBot, viaBot) - val oldMessage = usersLocationMessages.values.firstOrNull { getSenderMessageId(it) == getSenderMessageId(message) && !fromBot && !viaBot } - val hasNewerMessage = oldMessage != null && (Math.max(message.editDate, message.date) < Math.max(oldMessage.editDate, oldMessage.date)) - if (!hasNewerMessage) { - usersLocationMessages[message.id] = message - } - incomingMessagesListeners.forEach { - if (!hasNewerMessage || it is TelegramService) { - it.onReceiveChatLocationMessages(message.chatId, message) - } + removeOldMessages(message, fromBot, viaBot) + val oldMessage = usersLocationMessages.values.firstOrNull { getSenderMessageId(it) == getSenderMessageId(message) && !fromBot && !viaBot } + val hasNewerMessage = oldMessage != null && (Math.max(message.editDate, message.date) < Math.max(oldMessage.editDate, oldMessage.date)) + if (!hasNewerMessage) { + usersLocationMessages[message.id] = message + } + incomingMessagesListeners.forEach { + if (!hasNewerMessage || it is TelegramService) { + it.onReceiveChatLocationMessages(message.chatId, message) } } } @@ -908,7 +901,7 @@ class TelegramHelper private constructor() { private fun handleMapLocationMessageUpdate(obj: TdApi.Object, shareInfo: TelegramSettings.ShareChatInfo) { when (obj.constructor) { TdApi.Error.CONSTRUCTOR -> { - log.debug("handleMapLocationMessageUpdate - ERROR") + log.debug("handleMapLocationMessageUpdate - ERROR $obj") val error = obj as TdApi.Error needRefreshActiveLiveLocationMessages = true if (error.code == MESSAGE_CANNOT_BE_EDITED_ERROR_CODE) { @@ -973,7 +966,6 @@ class TelegramHelper private constructor() { when { obj.sendingState?.constructor == TdApi.MessageSendingStateFailed.CONSTRUCTOR -> { shareInfo.hasSharingError = true - shareInfo.pendingTdLib-- shareInfo.pendingTextMessage = false needRefreshActiveLiveLocationMessages = true log.debug("handleTextLocationMessageUpdate - MessageSendingStateFailed") @@ -1317,26 +1309,10 @@ class TelegramHelper private constructor() { } } } - TdApi.UpdateMessageEdited.CONSTRUCTOR -> { - val updateMessageEdited = obj as TdApi.UpdateMessageEdited - val message = usersLocationMessages[updateMessageEdited.messageId] - if (message == null) { - updateMessageEdited.apply { - requestMessage(chatId, messageId, this@TelegramHelper::addNewMessage) - } - } else { - synchronized(message) { - message.editDate = updateMessageEdited.editDate - lastTelegramUpdateTime = Math.max(message.date, message.editDate) - } - incomingMessagesListeners.forEach { - it.updateLocationMessages() - } - } - } TdApi.UpdateMessageContent.CONSTRUCTOR -> { val updateMessageContent = obj as TdApi.UpdateMessageContent val message = usersLocationMessages[updateMessageContent.messageId] + log.debug("UpdateMessageContent " + updateMessageContent.messageId) if (message == null) { updateMessageContent.apply { requestMessage(chatId, messageId, this@TelegramHelper::addNewMessage) @@ -1356,7 +1332,6 @@ class TelegramHelper private constructor() { newContent } } - log.debug("UpdateMessageContent " + message.senderUserId) incomingMessagesListeners.forEach { it.onReceiveChatLocationMessages(message.chatId, message) } @@ -1364,6 +1339,7 @@ class TelegramHelper private constructor() { } TdApi.UpdateNewMessage.CONSTRUCTOR -> { addNewMessage((obj as TdApi.UpdateNewMessage).message) + log.debug("UpdateNewMessage " + obj.message.id) } TdApi.UpdateMessageMentionRead.CONSTRUCTOR -> { val updateChat = obj as TdApi.UpdateMessageMentionRead diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt index aab31f3ba2..7f35438079 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt @@ -6,11 +6,10 @@ import android.widget.ImageView import net.osmand.data.LatLon import net.osmand.telegram.R import net.osmand.telegram.TelegramApplication -import net.osmand.telegram.utils.OsmandLocationUtils -import net.osmand.telegram.utils.OsmandLocationUtils.MessageUserTextLocation -import net.osmand.telegram.utils.OsmandLocationUtils.MessageOsmAndBotLocation -import net.osmand.telegram.utils.GPXUtilities import net.osmand.telegram.utils.GPXUtilities.GPXFile +import net.osmand.telegram.utils.OsmandLocationUtils +import net.osmand.telegram.utils.OsmandLocationUtils.MessageOsmAndBotLocation +import net.osmand.telegram.utils.OsmandLocationUtils.MessageUserLocation import org.drinkless.td.libcore.telegram.TdApi object TelegramUiHelper { @@ -71,7 +70,7 @@ object TelegramUiHelper { val content = message.content if (content is TdApi.MessageLocation) { res.latLon = LatLon(content.location.latitude, content.location.longitude) - } else if (content is MessageUserTextLocation) { + } else if (content is MessageUserLocation) { res.latLon = LatLon(content.lat, content.lon) } } @@ -112,7 +111,7 @@ object TelegramUiHelper { val content = message.content return when (content) { is MessageOsmAndBotLocation -> botMessageToLocationItem(chat, content) - is MessageUserTextLocation -> locationMessageToLocationItem(helper, chat, message) + is MessageUserLocation -> locationMessageToLocationItem(helper, chat, message) is TdApi.MessageLocation -> locationMessageToLocationItem(helper, chat, message) else -> null } @@ -127,7 +126,7 @@ object TelegramUiHelper { return when (content) { is MessageOsmAndBotLocation -> botMessageToChatItem(helper, chat, content) is TdApi.MessageLocation -> locationMessageToChatItem(helper, chat, message) - is MessageUserTextLocation -> locationMessageToChatItem(helper, chat, message) + is MessageUserLocation -> locationMessageToChatItem(helper, chat, message) else -> null } } @@ -167,7 +166,7 @@ object TelegramUiHelper { name = TelegramUiHelper.getUserName(user) latLon = when (content) { is TdApi.MessageLocation -> LatLon(content.location.latitude, content.location.longitude) - is MessageUserTextLocation -> LatLon(content.lat, content.lon) + is MessageUserLocation -> LatLon(content.lat, content.lon) else -> null } photoPath = helper.getUserPhotoPath(user) @@ -213,7 +212,7 @@ object TelegramUiHelper { name = TelegramUiHelper.getUserName(user) latLon = when (content) { is TdApi.MessageLocation -> LatLon(content.location.latitude, content.location.longitude) - is MessageUserTextLocation -> LatLon(content.lat, content.lon) + is MessageUserLocation -> LatLon(content.lat, content.lon) else -> null } if (helper.isGroup(chat)) { @@ -257,6 +256,33 @@ object TelegramUiHelper { } } + fun locationMessagesToChatItem( + helper: TelegramHelper, + messages: List + ): LocationMessagesChatItem? { + val message = messages.firstOrNull() + val user = helper.getUser(message?.userId ?: -1) ?: return null + val chat = helper.getChat(message?.chatId ?: -1) ?: return null + return LocationMessagesChatItem().apply { + chatId = chat.id + chatTitle = chat.title + locationMessages = messages + name = TelegramUiHelper.getUserName(user) + if (helper.isGroup(chat)) { + photoPath = helper.getUserPhotoPath(user) + groupPhotoPath = chat.photo?.small?.local?.path + } else { + photoPath = user.profilePhoto?.small?.local?.path + } + grayscalePhotoPath = helper.getUserGreyPhotoPath(user) + placeholderId = R.drawable.img_user_picture + userId = user.id + privateChat = helper.isPrivateChat(chat) || helper.isSecretChat(chat) + chatWithBot = helper.isBot(userId) + lastUpdated = (messages.maxBy { it.time }?.time ?: -1).toInt() + } + } + private fun gpxToUserGpxChatItem( helper: TelegramHelper, gpx: GPXFile @@ -340,6 +366,24 @@ object TelegramUiHelper { override fun getVisibleName() = chatTitle } + class LocationMessagesChatItem : ListItem() { + + var locationMessages: List = emptyList() + internal set + var groupPhotoPath: String? = null + internal set + var privateChat: Boolean = false + internal set + var chatWithBot: Boolean = false + internal set + + override fun canBeOpenedOnMap() = latLon != null + + override fun getMapPointId() = "${chatId}_$userId" + + override fun getVisibleName() = chatTitle + } + class LocationItem : ListItem() { override fun canBeOpenedOnMap() = latLon != null diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/MainActivity.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/MainActivity.kt index b536cc6770..50b1f4759f 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/MainActivity.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/MainActivity.kt @@ -294,10 +294,7 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene } if (app.telegramService == null) { messages.forEach { - val locationMessage = OsmandLocationUtils.parseMessage(it, telegramHelper) - if (locationMessage != null) { - app.locationMessages.addLocationMessage(locationMessage) - } + app.locationMessages.addNewLocationMessage(it) } } } diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt index f49f781aae..75d06c5e3f 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt @@ -231,7 +231,6 @@ class MyLocationTabFragment : Fragment(), TelegramListener { override fun onResume() { super.onResume() updateCurrentUserPhoto() - telegramHelper.getActiveLiveLocationMessages(null) updateContent() updateEnable = true startHandler() @@ -719,7 +718,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener { } holder.gpsPointsCollected?.apply { if (shareInfo != null) { - text = "${shareInfo.collectedMessages}" + val bufferedMessages = shareInfo.pendingTdLib + app.locationMessages.getBufferedMessagesForChat(shareInfo.chatId).size + text = "$bufferedMessages" } } holder.gpsPointsSent?.apply { diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/TimelineTabFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/TimelineTabFragment.kt index bb20bc491c..c231f0afd5 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/TimelineTabFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/TimelineTabFragment.kt @@ -18,12 +18,12 @@ import android.widget.TextView import net.osmand.PlatformUtil import net.osmand.telegram.R import net.osmand.telegram.TelegramApplication +import net.osmand.telegram.helpers.LocationMessages import net.osmand.telegram.helpers.TelegramUiHelper import net.osmand.telegram.helpers.TelegramUiHelper.ListItem import net.osmand.telegram.ui.TimelineTabFragment.LiveNowListAdapter.BaseViewHolder import net.osmand.telegram.utils.AndroidUtils import net.osmand.telegram.utils.OsmandFormatter -import net.osmand.telegram.utils.OsmandLocationUtils import java.util.* @@ -39,8 +39,7 @@ class TimelineTabFragment : Fragment() { private lateinit var adapter: LiveNowListAdapter - private lateinit var dateStartBtn: TextView - private lateinit var dateEndBtn: TextView + private lateinit var dateBtn: TextView private lateinit var mainView: View private var start = 0L @@ -77,21 +76,13 @@ class TimelineTabFragment : Fragment() { monitoringTv.setText(if (monitoringEnabled) R.string.monitoring_is_enabled else R.string.monitoring_is_disabled) } - dateStartBtn = mainView.findViewById(R.id.date_start_btn).apply { + dateBtn = mainView.findViewById(R.id.date_btn).apply { setOnClickListener { - selectStartDate() + selectDate() } setCompoundDrawablesWithIntrinsicBounds(getPressedStateIcon(R.drawable.ic_action_date_start), null, null, null) + setTextColor(AndroidUtils.createPressedColorStateList(app, true, R.color.ctrl_active_light, R.color.ctrl_light)) } - dateEndBtn = mainView.findViewById(R.id.date_end_btn).apply { - setOnClickListener { - selectEndDate() - } - setCompoundDrawablesWithIntrinsicBounds(getPressedStateIcon(R.drawable.ic_action_date_add), null, null, null) - } - - setupBtnTextColor(dateStartBtn) - setupBtnTextColor(dateEndBtn) return mainView } @@ -107,24 +98,28 @@ class TimelineTabFragment : Fragment() { updateEnable = false } - private fun setupBtnTextColor(textView: TextView) { - textView.setTextColor(AndroidUtils.createPressedColorStateList(app, true, R.color.ctrl_active_light, R.color.ctrl_light)) - } - - private fun selectStartDate() { + private fun selectDate() { val dateFromDialog = DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth -> val from = Calendar.getInstance() from.set(Calendar.YEAR, year) from.set(Calendar.MONTH, monthOfYear) from.set(Calendar.DAY_OF_MONTH, dayOfMonth) + from.set(Calendar.HOUR_OF_DAY, 0) from.clear(Calendar.MINUTE) from.clear(Calendar.SECOND) from.clear(Calendar.MILLISECOND) start = from.timeInMillis + + from.set(Calendar.HOUR_OF_DAY, 23) + from.set(Calendar.MINUTE, 59) + from.set(Calendar.SECOND, 59) + from.set(Calendar.MILLISECOND, 999) + end = from.timeInMillis + updateList() - updateDateButtons() + updateDateButton() } val startCalendar = Calendar.getInstance() startCalendar.timeInMillis = start @@ -135,34 +130,8 @@ class TimelineTabFragment : Fragment() { ).show() } - private fun selectEndDate() { - val dateFromDialog = - DatePickerDialog.OnDateSetListener { _, year, monthOfYear, dayOfMonth -> - val from = Calendar.getInstance() - from.set(Calendar.YEAR, year) - from.set(Calendar.MONTH, monthOfYear) - from.set(Calendar.DAY_OF_MONTH, dayOfMonth) - from.set(Calendar.HOUR_OF_DAY, 23) - from.set(Calendar.MINUTE, 59) - from.set(Calendar.SECOND, 59) - from.set(Calendar.MILLISECOND, 999) - end = from.timeInMillis - updateList() - updateDateButtons() - } - val endCalendar = Calendar.getInstance() - endCalendar.timeInMillis = end - DatePickerDialog(context, dateFromDialog, - endCalendar.get(Calendar.YEAR), - endCalendar.get(Calendar.MONTH), - endCalendar.get(Calendar.DAY_OF_MONTH) - ).show() - } - - private fun updateDateButtons() { - dateStartBtn.text = OsmandFormatter.getFormattedDate(start / 1000) - dateEndBtn.text = OsmandFormatter.getFormattedDate(end / 1000) - dateEndBtn.setCompoundDrawablesWithIntrinsicBounds(getPressedStateIcon(R.drawable.ic_action_date_end), null, null, null) + private fun updateDateButton() { + dateBtn.text = OsmandFormatter.getFormattedDate(start / 1000) } private fun getPressedStateIcon(@DrawableRes iconId: Int): Drawable? { @@ -188,22 +157,19 @@ class TimelineTabFragment : Fragment() { private fun updateList() { val res = mutableListOf() - val ignoredUsersIds = ArrayList() val currentUserId = telegramHelper.getCurrentUser()?.id if (currentUserId != null) { val outgoingMessages = app.locationMessages.getMessagesForUser(currentUserId, start, end) - // todo - why do we need convert to gpx on update? Is locationMessages not enough to display info? - OsmandLocationUtils.convertLocationMessagesToGpxFiles(outgoingMessages, false).forEach { - TelegramUiHelper.gpxToChatItem(telegramHelper, it, true)?.also { chatItem -> + TelegramUiHelper.locationMessagesToChatItem(telegramHelper, outgoingMessages)?.also { chatItem -> res.add(chatItem) } - } - ignoredUsersIds.add(currentUserId) val ingoingMessages = app.locationMessages.getIngoingMessages(currentUserId, start, end) - OsmandLocationUtils.convertLocationMessagesToGpxFiles(ingoingMessages).forEach { - TelegramUiHelper.gpxToChatItem(telegramHelper, it, false)?.also { chatItem -> - res.add(chatItem) - } + val emm = ingoingMessages.distinctBy { Pair(it.userId, it.chatId) } + emm.forEach { message -> + TelegramUiHelper.locationMessagesToChatItem(telegramHelper, + ingoingMessages.filter { it.chatId == message.chatId && it.userId == message.userId })?.also { chatItem -> + res.add(chatItem) + } } } @@ -245,24 +211,17 @@ class TimelineTabFragment : Fragment() { holder.bottomShadow?.visibility = if (lastItem) View.VISIBLE else View.GONE holder.lastTelegramUpdateTime?.visibility = View.GONE - if (item is TelegramUiHelper.GpxChatItem) { - val gpx = item.gpxFile - val groupDescrRowVisible = (!item.privateChat || item.chatWithBot) && item.userId != currentUserId - if (groupDescrRowVisible) { - holder.groupDescrContainer?.visibility = View.VISIBLE - holder.groupTitle?.text = item.getVisibleName() - TelegramUiHelper.setupPhoto(app, holder.groupImage, item.groupPhotoPath, item.placeholderId, false) - } else { - holder.groupDescrContainer?.visibility = View.GONE - } + if (item is TelegramUiHelper.LocationMessagesChatItem) { + val distance = OsmandFormatter.getFormattedDistance(getDistance(item.locationMessages),app) + val name = if ((!item.privateChat || item.chatWithBot) && item.userId != currentUserId) item.getVisibleName() else "" + holder.groupDescrContainer?.visibility = View.VISIBLE + holder.groupTitle?.text = "$distance (${getString(R.string.points_size, item.locationMessages.size)}) $name" + TelegramUiHelper.setupPhoto(app, holder.groupImage, item.groupPhotoPath, item.placeholderId, false) holder.userRow?.setOnClickListener { - if (gpx != null) { - childFragmentManager.also { - UserGpxInfoFragment.showInstance(it, gpx, start, end) - } + childFragmentManager.also { + UserGpxInfoFragment.showInstance(it, item.userId, item.chatId, start, end) } } - holder.imageButton?.visibility = View.GONE holder.showOnMapRow?.visibility = View.GONE holder.bottomDivider?.visibility = if (lastItem) View.GONE else View.VISIBLE @@ -270,6 +229,14 @@ class TimelineTabFragment : Fragment() { } } + private fun getDistance(messages: List): Float { + var dist = 0.0 + messages.forEach { + dist += it.distanceFromPrev + } + return dist.toFloat() + } + override fun getItemCount() = items.size inner class BaseViewHolder(view: View) : RecyclerView.ViewHolder(view) { diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/UserGpxInfoFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/UserGpxInfoFragment.kt index 6eaedd7a12..a8bb206d5a 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/UserGpxInfoFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/UserGpxInfoFragment.kt @@ -37,7 +37,7 @@ class UserGpxInfoFragment : BaseDialogFragment() { private val uiUtils get() = app.uiUtils - private lateinit var gpxFile: GPXUtilities.GPXFile + private var gpxFile = GPXUtilities.GPXFile() private lateinit var dateStartBtn: TextView private lateinit var timeStartBtn: TextView @@ -52,6 +52,9 @@ class UserGpxInfoFragment : BaseDialogFragment() { private var startCalendar = Calendar.getInstance() private var endCalendar = Calendar.getInstance() + private var userId = -1 + private var chatId = -1L + override fun onCreateView( inflater: LayoutInflater, parent: ViewGroup?, @@ -62,8 +65,6 @@ class UserGpxInfoFragment : BaseDialogFragment() { readFromBundle(savedInstanceState ?: arguments) - val userId = gpxFile.userId - val user = app.telegramHelper.getUser(userId) if (user != null) { mainView.findViewById(R.id.title).text = TelegramUiHelper.getUserName(user) @@ -79,8 +80,6 @@ class UserGpxInfoFragment : BaseDialogFragment() { } }) - updateGPXMap() - val backBtn = mainView.findViewById(R.id.back_button) backBtn.setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_arrow_back)) backBtn.setOnClickListener { @@ -169,6 +168,8 @@ class UserGpxInfoFragment : BaseDialogFragment() { } } + updateGpxInfo() + return mainView } @@ -197,6 +198,8 @@ class UserGpxInfoFragment : BaseDialogFragment() { private fun readFromBundle(bundle: Bundle?) { bundle?.also { + userId = it.getInt(USER_ID_KEY) + chatId = it.getLong(CHAT_ID_KEY) startCalendar.timeInMillis = it.getLong(START_KEY) endCalendar.timeInMillis = it.getLong(END_KEY) } @@ -207,14 +210,10 @@ class UserGpxInfoFragment : BaseDialogFragment() { } private fun updateGpxInfo() { -// gpxFile = OsmandLocationUtils.convertLocationMessagesToGpxFiles( -// app.locationMessages.collectRecordedDataForUser( -// gpxFile.userId, -// gpxFile.chatId, -// startCalendar.timeInMillis, -// endCalendar.timeInMillis -// ) -// ).first() + val emm = app.locationMessages.getMessagesForUserInChat( + userId, chatId, startCalendar.timeInMillis, endCalendar.timeInMillis) + + gpxFile = OsmandLocationUtils.convertLocationMessagesToGpxFiles(emm).firstOrNull()?:GPXUtilities.GPXFile() updateGPXStatisticRow() updateDateAndTimeButtons() updateGPXMap() @@ -308,18 +307,21 @@ class UserGpxInfoFragment : BaseDialogFragment() { private const val TAG = "UserGpxInfoFragment" private const val START_KEY = "start_key" private const val END_KEY = "end_key" + private const val USER_ID_KEY = "user_id_key" + private const val CHAT_ID_KEY = "chat_id_key" private const val GPX_TRACK_COLOR = -65536 - fun showInstance(fm: FragmentManager, gpxFile: GPXUtilities.GPXFile, start: Long, end: Long): Boolean { + fun showInstance(fm: FragmentManager,userId:Int,chatId:Long, start: Long, end: Long): Boolean { return try { val fragment = UserGpxInfoFragment().apply { arguments = Bundle().apply { + putInt(USER_ID_KEY, userId) + putLong(CHAT_ID_KEY, chatId) putLong(START_KEY, start) putLong(END_KEY, end) } } - fragment.gpxFile = gpxFile fragment.show(fm, TAG) true } catch (e: RuntimeException) { diff --git a/OsmAnd-telegram/src/net/osmand/telegram/utils/OsmandLocationUtils.kt b/OsmAnd-telegram/src/net/osmand/telegram/utils/OsmandLocationUtils.kt index cc54ad06f5..612cabcfac 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/utils/OsmandLocationUtils.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/utils/OsmandLocationUtils.kt @@ -9,6 +9,7 @@ import net.osmand.telegram.helpers.LocationMessages.LocationMessage import net.osmand.telegram.helpers.TelegramHelper import net.osmand.telegram.helpers.TelegramUiHelper import net.osmand.util.GeoPointParserUtil +import net.osmand.util.MapUtils import org.drinkless.td.libcore.telegram.TdApi import java.io.File import java.text.SimpleDateFormat @@ -48,7 +49,7 @@ object OsmandLocationUtils { val content = message.content return when (content) { is MessageOsmAndBotLocation -> content.lastUpdated - is MessageUserTextLocation -> content.lastUpdated + is MessageUserLocation -> content.lastUpdated else -> Math.max(message.editDate, message.date) } } @@ -76,49 +77,79 @@ object OsmandLocationUtils { } } - fun parseMessage(message: TdApi.Message, helper: TelegramHelper): LocationMessage? { + fun parseUserMapLocation(message: TdApi.Message): MessageUserLocation { + val messageLocation = message.content as TdApi.MessageLocation + return MessageUserLocation().apply { + lat = messageLocation.location.latitude + lon = messageLocation.location.longitude + lastUpdated = getLastUpdatedTime(message) + } + } + + fun parseMessage(message: TdApi.Message, helper: TelegramHelper, previousMessage: LocationMessage?): LocationMessage? { var locationMessage: LocationMessage? = null val oldContent = message.content - - val fromBot = helper.isOsmAndBot(message.senderUserId) - val viaBot = helper.isOsmAndBot(message.viaBotUserId) - - var messageType: Int = -1 - val parsedMessageContent = - if (oldContent is TdApi.MessageText) { - when { - oldContent.text.text.startsWith(DEVICE_PREFIX) -> { - messageType = LocationMessages.TYPE_BOT_TEXT - parseTextLocation(oldContent.text) - } - oldContent.text.text.startsWith(USER_TEXT_LOCATION_TITLE) -> { - messageType = LocationMessages.TYPE_USER_TEXT - parseTextLocation(oldContent.text, false) - } - else -> null + val messageType = getMessageType(message,helper) + var parsedMessageContent: MessageLocation? = null + if (messageType != -1) { + parsedMessageContent = when (messageType) { + LocationMessages.TYPE_BOT_TEXT -> { + parseTextLocation((oldContent as TdApi.MessageText).text) } - } else if (oldContent is TdApi.MessageLocation && (fromBot || viaBot)) { - messageType = LocationMessages.TYPE_BOT_MAP - parseOsmAndBotLocation(message) - } else if (oldContent is MessageLocation) { - messageType = 0 - oldContent - } else { - null + LocationMessages.TYPE_USER_TEXT -> { + if (oldContent is TdApi.MessageText) { + parseTextLocation(oldContent.text, false) + } else { + oldContent as MessageUserLocation + } + } + LocationMessages.TYPE_BOT_MAP -> { + parseOsmAndBotLocation(message) + } + LocationMessages.TYPE_USER_MAP -> { + parseUserMapLocation(message) + } + else -> null } + } if (parsedMessageContent != null) { + val distanceFromPrev = if (previousMessage != null) { + MapUtils.getDistance(previousMessage.lat, previousMessage.lon, + parsedMessageContent.lat, parsedMessageContent.lon) + } else 0.0 + locationMessage = LocationMessage(helper.getSenderMessageId(message), message.chatId, parsedMessageContent.lat, parsedMessageContent.lon, parsedMessageContent.altitude, parsedMessageContent.speed, parsedMessageContent.hdop, - parsedMessageContent.bearing, parsedMessageContent.lastUpdated * 1000L, messageType) - } else if(oldContent is TdApi.MessageLocation){ - locationMessage = LocationMessage(helper.getSenderMessageId(message), message.chatId, oldContent.location.latitude, - oldContent.location.longitude, 0.0, 0.0, 0.0, - 0.0, getLastUpdatedTime(message) * 1000L, LocationMessages.TYPE_USER_MAP) + parsedMessageContent.bearing, parsedMessageContent.lastUpdated * 1000L, messageType, message.id, distanceFromPrev) } + return locationMessage } + fun getMessageType(message: TdApi.Message, helper: TelegramHelper): Int { + val fromBot = helper.isOsmAndBot(message.senderUserId) + val viaBot = helper.isOsmAndBot(message.viaBotUserId) + val oldContent = message.content + return if (oldContent is TdApi.MessageText) { + if (fromBot || viaBot) { + LocationMessages.TYPE_BOT_TEXT + } else { + LocationMessages.TYPE_USER_TEXT + } + } else if (oldContent is TdApi.MessageLocation) { + if (fromBot || viaBot) { + LocationMessages.TYPE_BOT_MAP + } else { + LocationMessages.TYPE_USER_MAP + } + } else if (oldContent is MessageLocation) { + oldContent.type + } else { + -1 + } + } + fun formatLocation(sig: Location): String { return String.format(Locale.US, "%.5f, %.5f", sig.latitude, sig.longitude) } @@ -148,7 +179,7 @@ object OsmandLocationUtils { } fun parseTextLocation(text: TdApi.FormattedText, botLocation: Boolean = true): MessageLocation { - val res = if (botLocation) MessageOsmAndBotLocation() else MessageUserTextLocation() + val res = if (botLocation) MessageOsmAndBotLocation() else MessageUserLocation() res.type = if (botLocation) LocationMessages.TYPE_BOT_TEXT else LocationMessages.TYPE_USER_TEXT var locationNA = false for (s in text.text.lines()) { @@ -460,7 +491,7 @@ object OsmandLocationUtils { override fun isValid() = name != "" && lat != Double.NaN && lon != Double.NaN } - class MessageUserTextLocation : MessageLocation() { + class MessageUserLocation : MessageLocation() { override fun isValid() = lat != Double.NaN && lon != Double.NaN