diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt index c1f8a09717..31dbfb0bbe 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramService.kt @@ -277,7 +277,9 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis override fun onReceiveChatLocationMessages(chatId: Long, vararg messages: TdApi.Message) { app().showLocationHelper.startShowMessagesTask(chatId, *messages) messages.forEach { - app().locationMessages.addNewLocationMessage(it) + if (!it.isOutgoing) { + app().locationMessages.addNewLocationMessage(it) + } } } @@ -294,7 +296,9 @@ 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)) { - app().locationMessages.addNewLocationMessage(it) + if (!it.isOutgoing) { + 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 ea5e870fbb..40d009ea0c 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt @@ -360,7 +360,7 @@ class TelegramSettings(private val app: TelegramApplication) { if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) { val loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER) val gpsActive = loc != null && ((statusChangeTime - loc.time) / 1000) < GPS_UPDATE_EXPIRED_TIME - val lastSentLocationExpired = ((statusChangeTime - app.shareLocationHelper.lastLocationMessageSentTime) / 1000) > GPS_UPDATE_EXPIRED_TIME + val lastSentLocationExpired = ((statusChangeTime - app.shareLocationHelper.lastLocationUpdateTime) / 1000) > GPS_UPDATE_EXPIRED_TIME (gpsActive || !lastSentLocationExpired) } else { false @@ -393,7 +393,7 @@ class TelegramSettings(private val app: TelegramApplication) { } else if (!initializing) { when { !gpsEnabled -> { - locationTime = app.shareLocationHelper.lastLocationMessageSentTime + locationTime = app.shareLocationHelper.lastLocationUpdateTime if (locationTime <= 0) { locationTime = getLastSuccessfulSendTime() } diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt index 591629780b..4b736d668b 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/LocationMessages.kt @@ -4,19 +4,21 @@ import android.content.Context import android.database.Cursor import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteOpenHelper +import net.osmand.Location import net.osmand.PlatformUtil +import net.osmand.data.LatLon import net.osmand.telegram.TelegramApplication import net.osmand.telegram.utils.OsmandLocationUtils +import net.osmand.util.MapUtils import org.drinkless.td.libcore.telegram.TdApi class LocationMessages(val app: TelegramApplication) { private val log = PlatformUtil.getLog(LocationMessages::class.java) - // 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 var lastLocationPoints = mutableMapOf() private val dbHelper: SQLiteHelper @@ -33,11 +35,14 @@ class LocationMessages(val app: TelegramApplication) { return bufferedMessages.filter { it.chatId==chatId }.sortedBy { it.time } } - // todo - read from db by date (Victor's suggestion - filter by one day only. Need to be changed in UI also. fun getIngoingMessages(currentUserId: Int, start: Long, end: Long): List { return dbHelper.getIngoingMessages(currentUserId, start, end) } + fun getIngoingUserLocations(currentUserId: Int, start: Long, end: Long): List { + return dbHelper.getIngoingUserLocations(currentUserId, start, end) + } + fun getMessagesForUserInChat(userId: Int, chatId: Long, start: Long, end: Long): List { return dbHelper.getMessagesForUserInChat(userId, chatId, start, end) } @@ -46,6 +51,10 @@ class LocationMessages(val app: TelegramApplication) { return dbHelper.getMessagesForUser(userId, start, end) } + fun getUserLocations(userId: Int, start: Long, end: Long): UserLocations? { + return dbHelper.getUserLocations(userId, start, end) + } + fun addBufferedMessage(message: BufferMessage) { log.debug("addBufferedMessage $message") val messages = mutableListOf(*this.bufferedMessages.toTypedArray()) @@ -58,17 +67,28 @@ class LocationMessages(val app: TelegramApplication) { 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) + val newItem = LocationHistoryPoint(message.senderUserId, message.chatId, type) + val previousMessageLatLon = lastLocationPoints[newItem] + val locationMessage = OsmandLocationUtils.parseMessage(message, app.telegramHelper, previousMessageLatLon) if (locationMessage != null) { dbHelper.addLocationMessage(locationMessage) - val messages = mutableListOf(*this.lastMessages.toTypedArray()) - messages.remove(previousMessage) - messages.add(locationMessage) - this.lastMessages = messages + lastLocationPoints[newItem] = LatLon(locationMessage.lat, locationMessage.lon) } } + fun addMyLocationMessage(loc: Location) { + log.debug("addMyLocationMessage") + val currentUserId = app.telegramHelper.getCurrentUserId() + val newItem = LocationHistoryPoint(currentUserId, 0, -1) + val previousMessageLatLon = lastLocationPoints[newItem] + val distance = if (previousMessageLatLon != null) { MapUtils.getDistance(previousMessageLatLon, loc.latitude, loc.longitude) } else 0.0 + val message = LocationMessages.LocationMessage(currentUserId, 0, loc.latitude, loc.longitude, loc.altitude, + loc.speed.toDouble(), loc.accuracy.toDouble(), loc.bearing.toDouble(), loc.time, -1, 0, distance) + + dbHelper.addLocationMessage(message) + lastLocationPoints[newItem] = LatLon(message.lat, message.lon) + } + fun clearBufferedMessages() { log.debug("clearBufferedMessages") dbHelper.clearBufferedMessages() @@ -88,7 +108,7 @@ class LocationMessages(val app: TelegramApplication) { } private fun readLastMessages() { - this.lastMessages = dbHelper.getLastMessages() + this.lastLocationPoints = dbHelper.getLastMessages() } private class SQLiteHelper(context: Context) : @@ -121,7 +141,7 @@ class LocationMessages(val app: TelegramApplication) { internal fun getMessagesForUser(userId: Int, start: Long, end: Long): List { val res = arrayListOf() readableDatabase?.rawQuery( - "$TIMELINE_TABLE_SELECT WHERE $COL_USER_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_CHAT_ID ASC, $COL_TYPE DESC, $COL_TIME ASC ", arrayOf(userId.toString()))?.apply { if (moveToFirst()) { do { @@ -133,6 +153,33 @@ class LocationMessages(val app: TelegramApplication) { return res } + internal fun getUserLocations(userId: Int, start: Long, end: Long): UserLocations? { + var userLocations: UserLocations? = null + readableDatabase?.rawQuery( + "$TIMELINE_TABLE_SELECT WHERE $COL_USER_ID = ? AND $COL_TIME BETWEEN $start AND $end ORDER BY $COL_CHAT_ID ASC, $COL_TYPE DESC, $COL_TIME ASC ", + arrayOf(userId.toString()))?.apply { + var type = -1 + val userLocationsMap: MutableMap> = mutableMapOf() + userLocations = UserLocations(userId, 0, emptyMap()) + var userLocationsListBytetype: MutableList? = null + if (moveToFirst()) { + do { + val locationMessage = readLocationMessage(this@apply) + if (type != locationMessage.type) { + type = locationMessage.type + userLocationsListBytetype = mutableListOf() + userLocationsListBytetype.add(locationMessage) + userLocationsMap.set(type, userLocationsListBytetype) + } else { + userLocationsListBytetype?.add(locationMessage) + } + } while (moveToNext()) + } + close() + } + return userLocations + } + internal fun getPreviousMessage(userId: Int, chatId: Long): LocationMessage? { var res:LocationMessage? = null readableDatabase?.rawQuery( @@ -149,7 +196,7 @@ class LocationMessages(val app: TelegramApplication) { internal fun getIngoingMessages(currentUserId: Int, start: Long, end: Long): List { val res = arrayListOf() readableDatabase?.rawQuery( - "$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 ", + "$TIMELINE_TABLE_SELECT WHERE $COL_USER_ID != ? AND $COL_TIME BETWEEN $start AND $end ORDER BY $COL_USER_ID, $COL_CHAT_ID, $COL_TYPE DESC, $COL_TIME ", arrayOf(currentUserId.toString()))?.apply { if (moveToFirst()) { do { @@ -161,10 +208,50 @@ class LocationMessages(val app: TelegramApplication) { return res } + internal fun getIngoingUserLocations(currentUserId: Int, start: Long, end: Long): List { + val res = arrayListOf() + readableDatabase?.rawQuery( + "$TIMELINE_TABLE_SELECT WHERE $COL_USER_ID != ? AND $COL_TIME BETWEEN $start AND $end ORDER BY $COL_USER_ID, $COL_CHAT_ID, $COL_TYPE DESC, $COL_TIME ", + arrayOf(currentUserId.toString()))?.apply { + var type = -1 + var userId = -1 + var chatId = -1L + var userLocations: UserLocations? = null + var userLocationsMap: MutableMap>? = null + var userLocationsListBytetype: MutableList? = null + if (moveToFirst()) { + do { + val locationMessage = readLocationMessage(this@apply) + if (userId != locationMessage.userId || chatId != locationMessage.chatId) { + userId = locationMessage.userId + chatId = locationMessage.chatId + type = locationMessage.type + userLocationsMap = mutableMapOf() + userLocationsListBytetype = mutableListOf() + userLocationsListBytetype.add(locationMessage) + userLocationsMap[type] = userLocationsListBytetype + userLocations = UserLocations(userId, chatId, userLocationsMap) + res.add(userLocations) + } + if (type != locationMessage.type) { + type = locationMessage.type + userLocationsListBytetype = mutableListOf() + userLocationsListBytetype.add(locationMessage) + userLocationsMap?.set(type, userLocationsListBytetype) + } else { + userLocationsListBytetype?.add(locationMessage) + } + } while (moveToNext()) + } + close() + } + return res + } + 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 ", + "$TIMELINE_TABLE_SELECT WHERE $COL_USER_ID = ? AND $COL_CHAT_ID = ? AND $COL_TIME BETWEEN $start AND $end ORDER BY $COL_TYPE DESC, $COL_TIME ", arrayOf(userId.toString(), chatId.toString()))?.apply { if (moveToFirst()) { do { @@ -189,12 +276,12 @@ class LocationMessages(val app: TelegramApplication) { return res } - internal fun getLastMessages(): List { - val res = arrayListOf() - readableDatabase?.rawQuery(TIMELINE_TABLE_SELECT, null)?.apply { + internal fun getLastMessages(): MutableMap { + val res = mutableMapOf() + readableDatabase?.rawQuery("$TIMELINE_TABLE_SELECT_HISTORY_POINTS ORDER BY $COL_TIME ASC", null)?.apply { if (moveToFirst()) { do { - res.add(readLocationMessage(this@apply)) +// res.add(readLocationMessage(this@apply)) } while (moveToNext()) } close() @@ -233,6 +320,16 @@ class LocationMessages(val app: TelegramApplication) { return BufferMessage(chatId, lat, lon, altitude, speed, hdop, bearing, date, type) } + internal fun readLocationHistoryPoint(cursor: Cursor): Pair { + val userId = cursor.getInt(0) + val chatId = cursor.getLong(1) + val lat = cursor.getDouble(2) + val lon = cursor.getDouble(3) + val type = cursor.getInt(4) + + return Pair(LocationHistoryPoint(userId, chatId, type), LatLon(lat, lon)) + } + internal fun clearBufferedMessages() { writableDatabase?.execSQL(BUFFER_TABLE_CLEAR) } @@ -288,6 +385,9 @@ class LocationMessages(val app: TelegramApplication) { 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, $COL_DISTANCE_FROM_PREV FROM $TIMELINE_TABLE_NAME" + private const val TIMELINE_TABLE_SELECT_HISTORY_POINTS = + "SELECT $COL_USER_ID, $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_TIME, $COL_TYPE FROM $TIMELINE_TABLE_NAME" + private const val TIMELINE_TABLE_CLEAR = "DELETE FROM $TIMELINE_TABLE_NAME" private const val TIMELINE_TABLE_DELETE = "DROP TABLE IF EXISTS $TIMELINE_TABLE_NAME" @@ -335,6 +435,40 @@ class LocationMessages(val app: TelegramApplication) { val time: Long, val type: Int) + data class UserLocations( + var userId: Int, + var chatId: Long, + var locationsByType: Map> + ) + + data class LocationHistoryPoint( + val userId: Int, + val chatId: Long, + val type: Int + ) { + + override fun equals(other: Any?): Boolean { + if (other == null) { + return false + } + if (other !is LocationHistoryPoint) { + return false + } + val o = other as LocationHistoryPoint? + return this.userId == o!!.userId && this.chatId == o.chatId && this.type == o.type + } + + override fun hashCode(): Int { + val prime = 31 + var result = 1 + result = prime * result + userId.hashCode() + result = prime * result + chatId.hashCode() + result = prime * result + type.hashCode() + return result + } + } + + companion object { const val TYPE_USER_MAP = 0 diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/OsmandAidlHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/OsmandAidlHelper.kt index 621b2cb65f..412a05f97c 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/OsmandAidlHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/OsmandAidlHelper.kt @@ -203,6 +203,15 @@ class OsmandAidlHelper(private val app: TelegramApplication) { } } + fun execOsmandApi(action: (() -> Unit)) { + if (!isOsmandConnected() && isOsmandBound()) { + connectOsmand() + } + if (isOsmandConnected()) { + action.invoke() + } + } + private fun bindService(packageName: String): Boolean { return if (mIOsmAndAidlInterface == null) { val intent = Intent("net.osmand.aidl.OsmandAidlService") diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShareLocationHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShareLocationHelper.kt index 0d1dbc0796..fa874b0a50 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShareLocationHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShareLocationHelper.kt @@ -13,6 +13,8 @@ import org.json.JSONObject private const val USER_SET_LIVE_PERIOD_DELAY_MS = 5000 // 5 sec +private const val MY_LOCATION_UPDATE_MS = 15000 // 15 sec + class ShareLocationHelper(private val app: TelegramApplication) { private val log = PlatformUtil.getLog(ShareLocationHelper::class.java) @@ -26,7 +28,7 @@ class ShareLocationHelper(private val app: TelegramApplication) { var distance: Int = 0 private set - var lastLocationMessageSentTime: Long = 0 + var lastLocationUpdateTime: Long = 0 var lastLocation: Location? = null set(value) { @@ -52,7 +54,7 @@ class ShareLocationHelper(private val app: TelegramApplication) { if (app.settings.getChatsShareInfo().isNotEmpty()) { shareLocationMessages(location, app.telegramHelper.getCurrentUserId()) } - lastLocationMessageSentTime = System.currentTimeMillis() + lastLocationUpdateTime = System.currentTimeMillis() } app.settings.updateSharingStatusHistory() refreshNotification() @@ -188,6 +190,11 @@ class ShareLocationHelper(private val app: TelegramApplication) { val chatsShareInfo = app.settings.getChatsShareInfo() val latitude = location.latitude val longitude = location.longitude + val altitude = location.altitude + val speed = location.speed.toDouble() + val accuracy = location.accuracy.toDouble() + val bearing = location.bearing.toDouble() + val time = location.time val sharingMode = app.settings.currentSharingMode val isBot = sharingMode != userId.toString() var bufferedMessagesFull = false @@ -206,10 +213,7 @@ class ShareLocationHelper(private val app: TelegramApplication) { if (shareInfo.pendingTdLib >= 10) { bufferedMessagesFull = true } - val message = BufferMessage( - shareInfo.chatId, latitude, longitude, location.altitude, location.speed.toDouble(), - location.accuracy.toDouble(), location.bearing.toDouble(), System.currentTimeMillis(), type - ) + val message = BufferMessage(shareInfo.chatId, latitude, longitude, altitude, speed, accuracy, bearing, time, type) if (type == LocationMessages.TYPE_USER_MAP || type == LocationMessages.TYPE_BOT_MAP) { prepareMapMessage(shareInfo, message, isBot, sharingMode) @@ -219,6 +223,9 @@ class ShareLocationHelper(private val app: TelegramApplication) { prepareMapAndTextMessage(shareInfo, message, isBot, sharingMode) } } + if (System.currentTimeMillis() - lastLocationUpdateTime > MY_LOCATION_UPDATE_MS) { + app.locationMessages.addMyLocationMessage(location) + } if (bufferedMessagesFull) { checkNetworkType() } @@ -226,9 +233,9 @@ class ShareLocationHelper(private val app: TelegramApplication) { private fun prepareTextMessage(shareInfo: TelegramSettings.ShareChatInfo,message: BufferMessage,isBot:Boolean, sharingMode: String) { log.debug("prepareTextMessage $message") - shareInfo.collectedMessages++ if (shareInfo.currentTextMessageId == -1L) { if (shareInfo.pendingTextMessage) { + shareInfo.collectedMessages++ app.locationMessages.addBufferedMessage(message) } else { if (isBot) { @@ -244,6 +251,7 @@ class ShareLocationHelper(private val app: TelegramApplication) { if (shareInfo.pendingTdLib < 10) { app.telegramHelper.editTextLocation(shareInfo, message) } else { + shareInfo.collectedMessages++ app.locationMessages.addBufferedMessage(message) } } @@ -252,9 +260,9 @@ class ShareLocationHelper(private val app: TelegramApplication) { private fun prepareMapMessage(shareInfo: TelegramSettings.ShareChatInfo,message: BufferMessage,isBot:Boolean, sharingMode: String) { log.debug("prepareMapMessage $message") - shareInfo.collectedMessages++ if (shareInfo.currentMapMessageId == -1L) { if (shareInfo.pendingMapMessage) { + shareInfo.collectedMessages++ app.locationMessages.addBufferedMessage(message) } else { if (isBot) { @@ -279,8 +287,8 @@ class ShareLocationHelper(private val app: TelegramApplication) { private fun prepareMapAndTextMessage(shareInfo: TelegramSettings.ShareChatInfo, message: BufferMessage, isBot:Boolean, sharingMode: String) { log.debug("prepareMapAndTextMessage $message") - shareInfo.collectedMessages++ if (shareInfo.pendingMapMessage || shareInfo.pendingTextMessage || shareInfo.pendingTdLib >= 10) { + shareInfo.collectedMessages++ app.locationMessages.addBufferedMessage(message) } else { if (isBot) { diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShowLocationHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShowLocationHelper.kt index 44befe2886..e30fe971aa 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShowLocationHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/ShowLocationHelper.kt @@ -35,7 +35,7 @@ class ShowLocationHelper(private val app: TelegramApplication) { private var forcedStop: Boolean = false fun setupMapLayer() { - execOsmandApi { + osmandAidlHelper.execOsmandApi { osmandAidlHelper.addMapLayer(MAP_LAYER_ID, "Telegram", 5.5f, null) } } @@ -44,7 +44,7 @@ class ShowLocationHelper(private val app: TelegramApplication) { if (item.latLon == null) { return } - execOsmandApi { + osmandAidlHelper.execOsmandApi { osmandAidlHelper.showMapPoint( MAP_LAYER_ID, item.getMapPointId(), @@ -60,7 +60,7 @@ class ShowLocationHelper(private val app: TelegramApplication) { } fun updateLocationsOnMap() { - execOsmandApi { + osmandAidlHelper.execOsmandApi { val messages = telegramHelper.getMessages() for (message in messages) { val date = OsmandLocationUtils.getLastUpdatedTime(message) @@ -75,7 +75,7 @@ class ShowLocationHelper(private val app: TelegramApplication) { } fun addOrUpdateLocationOnMap(message: TdApi.Message, update: Boolean = false) { - execOsmandApi { + osmandAidlHelper.execOsmandApi { val chatId = message.chatId val chatTitle = telegramHelper.getChat(message.chatId)?.title val content = message.content @@ -133,7 +133,7 @@ class ShowLocationHelper(private val app: TelegramApplication) { } fun showChatMessages(chatId: Long) { - execOsmandApi { + osmandAidlHelper.execOsmandApi { val messages = telegramHelper.getChatMessages(chatId) for (message in messages) { addOrUpdateLocationOnMap(message) @@ -146,7 +146,7 @@ class ShowLocationHelper(private val app: TelegramApplication) { } fun hideMessages(messages: List) { - execOsmandApi { + osmandAidlHelper.execOsmandApi { for (message in messages) { val user = telegramHelper.getUser(message.senderUserId) if (user != null) { @@ -257,13 +257,4 @@ class ShowLocationHelper(private val app: TelegramApplication) { osmandAidlHelper.removeMapPoint(MAP_LAYER_ID, "${chatId}_${content.name}") } } - - private fun execOsmandApi(action: (() -> Unit)) { - if (!osmandAidlHelper.isOsmandConnected() && osmandAidlHelper.isOsmandBound()) { - osmandAidlHelper.connectOsmand() - } - if (osmandAidlHelper.isOsmandConnected()) { - action.invoke() - } - } } \ No newline at end of file diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt index 8e37e0ed1d..e3abd65635 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramHelper.kt @@ -1309,6 +1309,24 @@ class TelegramHelper private constructor() { } } } + TdApi.UpdateMessageEdited.CONSTRUCTOR -> { + val updateMessageEdited = obj as TdApi.UpdateMessageEdited + val message = usersLocationMessages[updateMessageEdited.messageId] + log.debug("UpdateMessageEdited " + 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] @@ -1325,9 +1343,12 @@ class TelegramHelper private constructor() { val viaBot = isOsmAndBot(message.viaBotUserId) message.content = if (newContent is TdApi.MessageText) { parseTextLocation(newContent.text, (fromBot || viaBot)) - } else if (newContent is TdApi.MessageLocation && - (isOsmAndBot(message.senderUserId) || isOsmAndBot(message.viaBotUserId))) { - parseOsmAndBotLocationContent(message.content as MessageOsmAndBotLocation, newContent) + } else if (newContent is TdApi.MessageLocation) { + if(fromBot||viaBot){ + parseOsmAndBotLocationContent(message.content as MessageOsmAndBotLocation, newContent) + } else { + OsmandLocationUtils.parseUserMapLocation(message) + } } else { newContent } diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt index 7f35438079..d86f2df7af 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt @@ -131,10 +131,6 @@ object TelegramUiHelper { } } - fun gpxToChatItem(helper: TelegramHelper, gpx: GPXFile, simpleUserItem: Boolean): GpxChatItem? { - return if (simpleUserItem) gpxToUserGpxChatItem(helper, gpx) else gpxToGpxChatItem(helper, gpx) - } - private fun botMessageToLocationItem( chat: TdApi.Chat, content: MessageOsmAndBotLocation @@ -256,47 +252,31 @@ 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 + fun userLocationsToChatItem(helper: TelegramHelper, userLocation: LocationMessages.UserLocations): LocationMessagesChatItem? { + val user = helper.getUser(userLocation.userId) + val chat = helper.getChat(userLocation.chatId) 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 + if (chat != null) { + chatId = chat.id + chatTitle = chat.title + if (helper.isGroup(chat)) { + photoPath = helper.getUserPhotoPath(user) + groupPhotoPath = chat.photo?.small?.local?.path + } else { + photoPath = user?.profilePhoto?.small?.local?.path + privateChat = helper.isPrivateChat(chat) || helper.isSecretChat(chat) + } } else { - photoPath = user.profilePhoto?.small?.local?.path + photoPath = user?.profilePhoto?.small?.local?.path } + if (user != null) { + name = TelegramUiHelper.getUserName(user) + userId = user.id + } + userLocations = userLocation 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 - ): GpxChatItem? { - val user = helper.getUser(gpx.userId) ?: return null - return GpxChatItem().apply { - gpxFile = gpx - name = TelegramUiHelper.getUserName(user) - photoPath = user.profilePhoto?.small?.local?.path - grayscalePhotoPath = helper.getUserGreyPhotoPath(user) - placeholderId = R.drawable.img_user_picture - userId = user.id - chatWithBot = helper.isBot(userId) - lastUpdated = (gpx.modifiedTime / 1000).toInt() } } @@ -368,7 +348,7 @@ object TelegramUiHelper { class LocationMessagesChatItem : ListItem() { - var locationMessages: List = emptyList() + var userLocations: LocationMessages.UserLocations? = null internal set var groupPhotoPath: String? = null internal set diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/MainActivity.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/MainActivity.kt index 50b1f4759f..6f6b880ad4 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/MainActivity.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/MainActivity.kt @@ -19,8 +19,6 @@ import android.widget.* 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.LocationMessages.LocationMessage import net.osmand.telegram.helpers.OsmandAidlHelper import net.osmand.telegram.helpers.TelegramHelper import net.osmand.telegram.helpers.TelegramHelper.* @@ -294,7 +292,9 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene } if (app.telegramService == null) { messages.forEach { + if (!it.isOutgoing) { 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 75d06c5e3f..38243f6704 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt @@ -718,8 +718,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener { } holder.gpsPointsCollected?.apply { if (shareInfo != null) { - val bufferedMessages = shareInfo.pendingTdLib + app.locationMessages.getBufferedMessagesForChat(shareInfo.chatId).size - text = "$bufferedMessages" + text = "${shareInfo.pendingTdLib + shareInfo.collectedMessages}" } } 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 c231f0afd5..de5ea5f48e 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/TimelineTabFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/TimelineTabFragment.kt @@ -159,18 +159,18 @@ class TimelineTabFragment : Fragment() { val res = mutableListOf() val currentUserId = telegramHelper.getCurrentUser()?.id if (currentUserId != null) { - val outgoingMessages = app.locationMessages.getMessagesForUser(currentUserId, start, end) - TelegramUiHelper.locationMessagesToChatItem(telegramHelper, outgoingMessages)?.also { chatItem -> - res.add(chatItem) - } - val ingoingMessages = app.locationMessages.getIngoingMessages(currentUserId, start, end) - 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 -> + val currentUserLocations = app.locationMessages.getUserLocations(currentUserId, start, end) + if (currentUserLocations != null) { + TelegramUiHelper.userLocationsToChatItem(telegramHelper, currentUserLocations)?.also { chatItem -> res.add(chatItem) } } + val ingoingUserLocations = app.locationMessages.getIngoingUserLocations(currentUserId, start, end) + ingoingUserLocations.forEach { + TelegramUiHelper.userLocationsToChatItem(telegramHelper, it)?.also { chatItem -> + res.add(chatItem) + } + } } adapter.items = sortAdapterItems(res) @@ -205,17 +205,21 @@ class TimelineTabFragment : Fragment() { val lastItem = position == itemCount - 1 val item = items[position] val currentUserId = telegramHelper.getCurrentUser()?.id ?: 0 - TelegramUiHelper.setupPhoto(app, holder.icon, item.photoPath, R.drawable.img_user_picture_active, false) holder.title?.text = item.name holder.bottomShadow?.visibility = if (lastItem) View.VISIBLE else View.GONE holder.lastTelegramUpdateTime?.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" + if (item is TelegramUiHelper.LocationMessagesChatItem ) { + val userLocations = item.userLocations + + if(userLocations!=null){ + val pair = getDistanceAndCountedPoints(userLocations) + val distance = OsmandFormatter.getFormattedDistance(pair.first,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, pair.second)}) $name" + } TelegramUiHelper.setupPhoto(app, holder.groupImage, item.groupPhotoPath, item.placeholderId, false) holder.userRow?.setOnClickListener { childFragmentManager.also { @@ -229,12 +233,27 @@ class TimelineTabFragment : Fragment() { } } - private fun getDistance(messages: List): Float { + private fun getDistanceAndCountedPoints(userLocations: LocationMessages.UserLocations): Pair { + val textUserLoc = userLocations.locationsByType[LocationMessages.TYPE_USER_TEXT] + val textBotLoc = userLocations.locationsByType[LocationMessages.TYPE_BOT_TEXT] var dist = 0.0 - messages.forEach { - dist += it.distanceFromPrev + var countedPoints = 0 + when { + textUserLoc != null -> textUserLoc.forEach { + dist += it.distanceFromPrev + countedPoints++ + } + textBotLoc != null -> textBotLoc.forEach { + dist += it.distanceFromPrev + countedPoints++ + } + else -> userLocations.locationsByType.values.firstOrNull()?.forEach { + dist += it.distanceFromPrev + countedPoints++ + } } - return dist.toFloat() + + return Pair(dist.toFloat(), countedPoints) } override fun getItemCount() = items.size diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/UserGpxInfoFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/UserGpxInfoFragment.kt index a8bb206d5a..bd3a784843 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/UserGpxInfoFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/UserGpxInfoFragment.kt @@ -20,12 +20,10 @@ import android.widget.Toast import net.osmand.PlatformUtil import net.osmand.aidl.gpx.AGpxBitmap import net.osmand.telegram.R +import net.osmand.telegram.helpers.LocationMessages import net.osmand.telegram.helpers.OsmandAidlHelper import net.osmand.telegram.helpers.TelegramUiHelper -import net.osmand.telegram.utils.AndroidUtils -import net.osmand.telegram.utils.GPXUtilities -import net.osmand.telegram.utils.OsmandFormatter -import net.osmand.telegram.utils.OsmandLocationUtils +import net.osmand.telegram.utils.* import net.osmand.util.Algorithms import java.io.File import java.text.SimpleDateFormat @@ -52,6 +50,8 @@ class UserGpxInfoFragment : BaseDialogFragment() { private var startCalendar = Calendar.getInstance() private var endCalendar = Calendar.getInstance() + private var locationMessages = emptyList() + private var userId = -1 private var chatId = -1L @@ -115,10 +115,10 @@ class UserGpxInfoFragment : BaseDialogFragment() { setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_speed_average)) } mainView.findViewById(R.id.distance_icon).apply { - setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_altitude_range)) + setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_sort_by_distance)) } mainView.findViewById(R.id.duration_icon).apply { - setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_altitude_range)) + setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_time_span)) } updateGPXStatisticRow() @@ -192,7 +192,8 @@ class UserGpxInfoFragment : BaseDialogFragment() { private fun saveCurrentGpxToFile(listener: OsmandLocationUtils.SaveGpxListener) { if (!gpxFile.isEmpty) { - OsmandLocationUtils.saveGpx(app, listener, app.getExternalFilesDir(null)!!, gpxFile) + val file = File(app.getExternalFilesDir(null), TRACKS_DIR) + OsmandLocationUtils.saveGpx(app, listener, file, gpxFile) } } @@ -210,10 +211,9 @@ class UserGpxInfoFragment : BaseDialogFragment() { } private fun updateGpxInfo() { - val emm = app.locationMessages.getMessagesForUserInChat( - userId, chatId, startCalendar.timeInMillis, endCalendar.timeInMillis) + locationMessages = app.locationMessages.getMessagesForUserInChat(userId, chatId, startCalendar.timeInMillis, endCalendar.timeInMillis) - gpxFile = OsmandLocationUtils.convertLocationMessagesToGpxFiles(emm).firstOrNull()?:GPXUtilities.GPXFile() + gpxFile = OsmandLocationUtils.convertLocationMessagesToGpxFiles(locationMessages).firstOrNull()?:GPXUtilities.GPXFile() updateGPXStatisticRow() updateDateAndTimeButtons() updateGPXMap() @@ -246,7 +246,9 @@ class UserGpxInfoFragment : BaseDialogFragment() { val widthPixels = dm.widthPixels - (2 * app.resources.getDimensionPixelSize(R.dimen.content_padding_standard)) val heightPixels = AndroidUtils.dpToPx(app, 152f) val gpxUri = AndroidUtils.getUriForFile(app, File(path)) - app.osmandAidlHelper.getBitmapForGpx(gpxUri, dm.density , widthPixels, heightPixels, GPX_TRACK_COLOR) + app.osmandAidlHelper.execOsmandApi { + app.osmandAidlHelper.getBitmapForGpx(gpxUri, dm.density , widthPixels, heightPixels, GPX_TRACK_COLOR) + } } } diff --git a/OsmAnd-telegram/src/net/osmand/telegram/utils/OsmandLocationUtils.kt b/OsmAnd-telegram/src/net/osmand/telegram/utils/OsmandLocationUtils.kt index 612cabcfac..6c8b10e533 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/utils/OsmandLocationUtils.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/utils/OsmandLocationUtils.kt @@ -2,6 +2,7 @@ package net.osmand.telegram.utils import android.os.AsyncTask import net.osmand.Location +import net.osmand.data.LatLon import net.osmand.telegram.TelegramApplication import net.osmand.telegram.helpers.LocationMessages import net.osmand.telegram.helpers.LocationMessages.BufferMessage @@ -15,6 +16,7 @@ import java.io.File import java.text.SimpleDateFormat import java.util.* +const val TRACKS_DIR = "tracker/" object OsmandLocationUtils { @@ -83,10 +85,11 @@ object OsmandLocationUtils { lat = messageLocation.location.latitude lon = messageLocation.location.longitude lastUpdated = getLastUpdatedTime(message) + type = LocationMessages.TYPE_USER_MAP } } - fun parseMessage(message: TdApi.Message, helper: TelegramHelper, previousMessage: LocationMessage?): LocationMessage? { + fun parseMessage(message: TdApi.Message, helper: TelegramHelper, previousMessageLatLon: LatLon?): LocationMessage? { var locationMessage: LocationMessage? = null val oldContent = message.content val messageType = getMessageType(message,helper) @@ -114,10 +117,8 @@ object OsmandLocationUtils { } if (parsedMessageContent != null) { - val distanceFromPrev = if (previousMessage != null) { - MapUtils.getDistance(previousMessage.lat, previousMessage.lon, - parsedMessageContent.lat, parsedMessageContent.lon) - } else 0.0 + val distanceFromPrev = if (previousMessageLatLon != null) { + MapUtils.getDistance(previousMessageLatLon, parsedMessageContent.lat, parsedMessageContent.lon) } else 0.0 locationMessage = LocationMessage(helper.getSenderMessageId(message), message.chatId, parsedMessageContent.lat, parsedMessageContent.lon, parsedMessageContent.altitude, parsedMessageContent.speed, parsedMessageContent.hdop, @@ -403,11 +404,16 @@ object OsmandLocationUtils { var segment: GPXUtilities.TrkSegment? = null var track: GPXUtilities.Track? = null var gpx: GPXUtilities.GPXFile? = null + var countedLocations = 0 items.forEach { val userId = it.userId val chatId = it.chatId val time = it.time + if (previousTime >= time) { + return@forEach + } + countedLocations++ if (previousUserId != userId || (newGpxPerChat && previousChatId != chatId)) { gpx = GPXUtilities.GPXFile() gpx!!.chatId = chatId @@ -521,10 +527,6 @@ object OsmandLocationUtils { userId.toString() + "_" + SimpleDateFormat("yyyy-MM-dd_HH-mm_EEE", Locale.US).format(Date(pt.time)) } fout = File(dir, "$fileName.gpx") - var ind = 1 - while (fout.exists()) { - fout = File(dir, "${fileName}_${++ind}.gpx") - } } val warn = GPXUtilities.writeGpxFile(fout, gpxFile, app) if (warn != null) {