db refactoring continues

This commit is contained in:
Chumva 2019-01-28 18:09:35 +02:00
parent 430ceb10ae
commit 256df2c866
9 changed files with 348 additions and 281 deletions

View file

@ -13,6 +13,7 @@ import android.os.*
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
import net.osmand.PlatformUtil import net.osmand.PlatformUtil
import net.osmand.telegram.helpers.LocationMessages
import net.osmand.telegram.helpers.LocationMessages.LocationMessage import net.osmand.telegram.helpers.LocationMessages.LocationMessage
import net.osmand.telegram.helpers.TelegramHelper.TelegramIncomingMessagesListener import net.osmand.telegram.helpers.TelegramHelper.TelegramIncomingMessagesListener
import net.osmand.telegram.helpers.TelegramHelper.TelegramOutgoingMessagesListener import net.osmand.telegram.helpers.TelegramHelper.TelegramOutgoingMessagesListener
@ -277,7 +278,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis
override fun onReceiveChatLocationMessages(chatId: Long, vararg messages: TdApi.Message) { override fun onReceiveChatLocationMessages(chatId: Long, vararg messages: TdApi.Message) {
app().showLocationHelper.startShowMessagesTask(chatId, *messages) app().showLocationHelper.startShowMessagesTask(chatId, *messages)
messages.forEach { messages.forEach {
val locationMessage = OsmandLocationUtils.parseMessage(it, app().telegramHelper, LocationMessage.STATUS_PREPARED) val locationMessage = OsmandLocationUtils.parseMessage(it, app().telegramHelper, LocationMessages.STATUS_PREPARED)
if (locationMessage != null) { if (locationMessage != null) {
app().locationMessages.addIngoingMessage(locationMessage) app().locationMessages.addIngoingMessage(locationMessage)
} }

View file

@ -845,13 +845,15 @@ class TelegramSettings(private val app: TelegramApplication) {
var updateTextMessageId = 1 var updateTextMessageId = 1
var currentMessageLimit = -1L var currentMessageLimit = -1L
var currentMapMessageId = -1L var currentMapMessageId = -1L
var oldMapMessageId = -1L
var currentTextMessageId = -1L var currentTextMessageId = -1L
var oldTextMessageId = -1L
var userSetLivePeriod = -1L var userSetLivePeriod = -1L
var userSetLivePeriodStart = -1L var userSetLivePeriodStart = -1L
var lastSuccessfulSendTimeMs = -1L var lastSuccessfulSendTimeMs = -1L
var lastSendTextMessageTime = -1 var lastSendTextMessageTime = -1
var lastSendMapMessageTime = -1 var lastSendMapMessageTime = -1
var bufferedMessages = 0 var pendingTdLib = 0
var pendingTextMessage = false var pendingTextMessage = false
var pendingMapMessage = false var pendingMapMessage = false
var shouldSendViaBotMessage = false var shouldSendViaBotMessage = false

View file

@ -11,7 +11,7 @@ import kotlin.collections.ArrayList
class LocationMessages(val app: TelegramApplication) { 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. // 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<LocationMessage>() private var bufferedMessages = emptyList<BufferMessage>()
private val dbHelper: SQLiteHelper private val dbHelper: SQLiteHelper
@ -20,27 +20,23 @@ class LocationMessages(val app: TelegramApplication) {
readBufferedMessages() readBufferedMessages()
} }
fun getPreparedMessages(): List<LocationMessage> { fun getPreparedMessages(): List<BufferMessage> {
val currentUserId = app.telegramHelper.getCurrentUserId() return bufferedMessages.sortedBy { it.date }
return bufferedMessages.filter { it.userId == currentUserId && it.status == LocationMessage.STATUS_PREPARED }.sortedBy { it.date }
} }
// todo - drop method. add collected / sent messages count to ShareChatInfo // // todo - drop method. add collected / sent messages count to ShareChatInfo
fun getOutgoingMessages(chatId: Long): List<LocationMessage> { // fun getOutgoingMessages(chatId: Long): List<LocationMessage> {
val currentUserId = app.telegramHelper.getCurrentUserId() // val currentUserId = app.telegramHelper.getCurrentUserId()
return bufferedMessages.filter { it.userId == currentUserId && it.chatId == chatId }.sortedBy { it.date } // return bufferedMessages.filter { it.userId == currentUserId && it.chatId == chatId }.sortedBy { it.date }
} // }
// todo - drop it or read from db fun updateBufferedMessageStatus(oldMessage: BufferMessage, status: Int){
fun getSentMessages(chatId: Long, date:Long): List<LocationMessage> { val messages = mutableListOf(*this.bufferedMessages.toTypedArray())
val currentUserId = app.telegramHelper.getCurrentUserId() messages.remove(oldMessage)
return bufferedMessages.filter { it.userId == currentUserId && it.chatId == chatId && it.date > date }.sortedBy { it.date } val newMessage = BufferMessage(oldMessage.chatId,oldMessage.lat,oldMessage.lon,oldMessage.altitude,oldMessage.speed,oldMessage.hdop,oldMessage.bearing,oldMessage.date,oldMessage.type,status)
} messages.add(newMessage)
this.bufferedMessages = messages
// todo - drop it or read from db // dbHelper.addBufferedMessage(newMessage)
fun getSentMessages(chatId: Long): List<LocationMessage> {
val currentUserId = app.telegramHelper.getCurrentUserId()
return bufferedMessages.filter { it.userId == currentUserId && it.chatId == chatId && it.status == LocationMessage.STATUS_SENT }.sortedBy { it.date }
} }
// todo - read from db by date (Victor's suggestion - filter by one day only. Need to be changed in UI also. // todo - read from db by date (Victor's suggestion - filter by one day only. Need to be changed in UI also.
@ -48,73 +44,78 @@ class LocationMessages(val app: TelegramApplication) {
return emptyList() return emptyList()
} }
fun addOutgoingMessage(message: LocationMessage) { fun addBufferedMessage(message: BufferMessage) {
val messages = mutableListOf(*this.bufferedMessages.toTypedArray()) val messages = mutableListOf(*this.bufferedMessages.toTypedArray())
messages.add(message) messages.add(message)
this.bufferedMessages = messages this.bufferedMessages = messages
dbHelper.addOutgoingMessage(message) dbHelper.addBufferedMessage(message)
} }
fun addIngoingMessage(message: LocationMessage) { fun addIngoingMessage(message: LocationMessage) {
dbHelper.addIngoingMessage(message) dbHelper.addIngoingMessage(message)
} }
fun clearOutgoingMessages() { fun clearBufferedMessages() {
dbHelper.clearOutgoingMessages() dbHelper.clearBufferedMessages()
bufferedMessages = emptyList() bufferedMessages = emptyList()
} }
// todo - both methods should be refactored since we have two tables now for outgoing/ingoing messages. Data should be read from db. // todo - both methods should be refactored since we have two tables now for outgoing/ingoing messages. Data should be read from db.
fun collectRecordedDataForUser(userId: Int, chatId: Long, start: Long, end: Long): List<LocationMessage> { // fun collectRecordedDataForUser(userId: Int, chatId: Long, start: Long, end: Long): List<LocationMessage> {
return if (chatId == 0L) { // return if (chatId == 0L) {
bufferedMessages.sortedWith(compareBy({ it.userId }, { it.chatId })).filter { it.userId == userId && it.date in (start + 1)..(end - 1) } // bufferedMessages.sortedWith(compareBy({ it.userId }, { it.chatId })).filter { it.userId == userId && it.date in (start + 1)..(end - 1) }
} else { // } else {
bufferedMessages.sortedWith(compareBy({ it.userId }, { it.chatId })).filter { // bufferedMessages.sortedWith(compareBy({ it.userId }, { it.chatId })).filter {
it.chatId == chatId && it.userId == userId && it.status == LocationMessage.STATUS_SENT && it.date in (start + 1)..(end - 1) } // it.chatId == chatId && it.userId == userId&&it.date in (start + 1)..(end - 1) }
} // }
} // }
//
fun collectRecordedDataForUsers(start: Long, end: Long, ignoredUsersIds: ArrayList<Int>): List<LocationMessage> { // fun collectRecordedDataForUsers(start: Long, end: Long, ignoredUsersIds: ArrayList<Int>): List<LocationMessage> {
return bufferedMessages.sortedWith(compareBy({ it.userId }, { it.chatId })).filter { // return bufferedMessages.sortedWith(compareBy({ it.userId }, { it.chatId })).filter {
it.date in (start + 1)..(end - 1) && !ignoredUsersIds.contains(it.userId) // it.date in (start + 1)..(end - 1) && !ignoredUsersIds.contains(it.userId)
} // }
} // }
private fun readBufferedMessages() { private fun readBufferedMessages() {
this.bufferedMessages = dbHelper.getOutgoingMessages(); this.bufferedMessages = dbHelper.getBufferedMessages()
} }
private class SQLiteHelper(context: Context) : private class SQLiteHelper(context: Context) :
SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) { SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
override fun onCreate(db: SQLiteDatabase) { override fun onCreate(db: SQLiteDatabase) {
db.execSQL(OUTGOING_TABLE_CREATE) db.execSQL(TIMELINE_TABLE_CREATE)
db.execSQL("CREATE INDEX $DATE_INDEX ON $OUTGOING_TABLE_NAME (\"$COL_DATE\" DESC);") db.execSQL("CREATE INDEX $DATE_INDEX ON $TIMELINE_TABLE_NAME (\"$COL_TIME\" DESC);")
db.execSQL(INGOING_TABLE_CREATE) db.execSQL(BUFFER_TABLE_CREATE)
db.execSQL("CREATE INDEX $DATE_INDEX ON $INGOING_TABLE_NAME (\"$COL_DATE\" DESC);")
} }
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL(OUTGOING_TABLE_DELETE) db.execSQL(TIMELINE_TABLE_DELETE)
db.execSQL(INGOING_TABLE_DELETE) db.execSQL(BUFFER_TABLE_DELETE)
onCreate(db) onCreate(db)
} }
internal fun addOutgoingMessage(message: LocationMessage) { internal fun addBufferedMessage(message: BufferMessage) {
writableDatabase?.execSQL(OUTGOING_TABLE_INSERT, writableDatabase?.execSQL(BUFFER_TABLE_INSERT,
arrayOf(message.userId, message.chatId, message.lat, message.lon, message.altitude, message.speed, arrayOf(message.chatId, message.lat, message.lon, message.altitude, message.speed,
message.hdop, message.bearing, message.date, message.type, message.status, message.messageId)) message.hdop, message.bearing, message.date, message.type))
} }
internal fun addIngoingMessage(message: LocationMessage) { internal fun addIngoingMessage(message: LocationMessage) {
writableDatabase?.execSQL(INGOING_TABLE_INSERT, writableDatabase?.execSQL(TIMELINE_TABLE_INSERT,
arrayOf(message.userId, message.chatId, message.lat, message.lon, message.altitude, message.speed, arrayOf(message.userId, message.chatId, message.lat, message.lon, message.altitude, message.speed,
message.hdop, message.bearing, message.date, message.type, message.status, message.messageId)) message.hdop, message.bearing, message.date, message.type))
}
internal fun addOutgoingMessage(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.date, message.type))
} }
internal fun getOutgoingMessages(): List<LocationMessage> { internal fun getOutgoingMessages(): List<LocationMessage> {
val res = arrayListOf<LocationMessage>() val res = arrayListOf<LocationMessage>()
readableDatabase?.rawQuery(OUTGOING_TABLE_SELECT, null)?.apply { readableDatabase?.rawQuery(TIMELINE_TABLE_SELECT, null)?.apply {
if (moveToFirst()) { if (moveToFirst()) {
do { do {
res.add(readLocationMessage(this@apply)) res.add(readLocationMessage(this@apply))
@ -125,6 +126,19 @@ class LocationMessages(val app: TelegramApplication) {
return res return res
} }
internal fun getBufferedMessages(): List<BufferMessage> {
val res = arrayListOf<BufferMessage>()
readableDatabase?.rawQuery(BUFFER_TABLE_SELECT, null)?.apply {
if (moveToFirst()) {
do {
res.add(readBufferMessage(this@apply))
} while (moveToNext())
}
close()
}
return res
}
internal fun readLocationMessage(cursor: Cursor): LocationMessage { internal fun readLocationMessage(cursor: Cursor): LocationMessage {
val userId = cursor.getInt(0) val userId = cursor.getInt(0)
val chatId = cursor.getLong(1) val chatId = cursor.getLong(1)
@ -136,27 +150,40 @@ class LocationMessages(val app: TelegramApplication) {
val bearing = cursor.getDouble(7) val bearing = cursor.getDouble(7)
val date = cursor.getLong(8) val date = cursor.getLong(8)
val type = cursor.getInt(9) val type = cursor.getInt(9)
val status = cursor.getInt(10)
val messageId = cursor.getLong(11)
return LocationMessage(userId, chatId, lat, lon, altitude, speed, hdop, bearing, date, type, status, messageId) return LocationMessage(userId, chatId, lat, lon, altitude, speed, hdop, bearing, date, type)
} }
internal fun clearOutgoingMessages() { internal fun readBufferMessage(cursor: Cursor): BufferMessage {
writableDatabase?.execSQL(OUTGOING_TABLE_CLEAR) val chatId = cursor.getLong(1)
val lat = cursor.getDouble(2)
val lon = cursor.getDouble(3)
val altitude = cursor.getDouble(4)
val speed = cursor.getDouble(5)
val hdop = cursor.getDouble(6)
val bearing = cursor.getDouble(7)
val date = cursor.getLong(8)
val type = cursor.getInt(9)
val status = cursor.getInt(10)
return BufferMessage(chatId, lat, lon, altitude, speed, hdop, bearing, date, type,status)
}
internal fun clearBufferedMessages() {
writableDatabase?.execSQL(BUFFER_TABLE_CLEAR)
} }
companion object { companion object {
private const val DATABASE_NAME = "location_messages" private const val DATABASE_NAME = "location_messages"
private const val DATABASE_VERSION = 3 private const val DATABASE_VERSION = 4
private const val OUTGOING_TABLE_NAME = "outgoing" private const val TIMELINE_TABLE_NAME = "timeline"
private const val INGOING_TABLE_NAME = "ingoing" private const val BUFFER_TABLE_NAME = "buffer"
private const val COL_USER_ID = "user_id" private const val COL_USER_ID = "user_id"
private const val COL_CHAT_ID = "chat_id" private const val COL_CHAT_ID = "chat_id"
private const val COL_DATE = "date" private const val COL_TIME = "time"
private const val COL_LAT = "lat" private const val COL_LAT = "lat"
private const val COL_LON = "lon" private const val COL_LON = "lon"
private const val COL_ALTITUDE = "altitude" private const val COL_ALTITUDE = "altitude"
@ -169,38 +196,49 @@ class LocationMessages(val app: TelegramApplication) {
private const val DATE_INDEX = "date_index" private const val DATE_INDEX = "date_index"
// Outgoing messages table // Timeline messages table
private const val OUTGOING_TABLE_INSERT = private const val TIMELINE_TABLE_INSERT =
("INSERT INTO $OUTGOING_TABLE_NAME ($COL_USER_ID, $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_DATE, $COL_TYPE, $COL_MESSAGE_STATUS, $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) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
private const val OUTGOING_TABLE_CREATE = private const val TIMELINE_TABLE_CREATE =
("CREATE TABLE IF NOT EXISTS $OUTGOING_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_DATE long, $COL_TYPE int, $COL_MESSAGE_STATUS 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 )")
private const val OUTGOING_TABLE_SELECT = 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_DATE, $COL_TYPE, $COL_MESSAGE_STATUS, $COL_MESSAGE_ID FROM $OUTGOING_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 FROM $TIMELINE_TABLE_NAME"
private const val OUTGOING_TABLE_CLEAR = "DELETE FROM $OUTGOING_TABLE_NAME" private const val TIMELINE_TABLE_CLEAR = "DELETE FROM $TIMELINE_TABLE_NAME"
private const val OUTGOING_TABLE_DELETE = "DROP TABLE IF EXISTS $OUTGOING_TABLE_NAME" private const val TIMELINE_TABLE_DELETE = "DROP TABLE IF EXISTS $TIMELINE_TABLE_NAME"
// Ingoing messages table // Buffer messages table
private const val INGOING_TABLE_INSERT = private const val BUFFER_TABLE_INSERT =
("INSERT INTO $INGOING_TABLE_NAME ($COL_USER_ID, $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_DATE, $COL_TYPE, $COL_MESSAGE_STATUS, $COL_MESSAGE_ID) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)") ("INSERT INTO $BUFFER_TABLE_NAME ($COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_TIME, $COL_TYPE, $COL_MESSAGE_STATUS) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
private const val INGOING_TABLE_CREATE = private const val BUFFER_TABLE_CREATE =
("CREATE TABLE IF NOT EXISTS $INGOING_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_DATE long, $COL_TYPE int, $COL_MESSAGE_STATUS int, $COL_MESSAGE_ID long )") ("CREATE TABLE IF NOT EXISTS $BUFFER_TABLE_NAME ($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_STATUS int)")
private const val INGOING_TABLE_SELECT = private const val BUFFER_TABLE_SELECT =
"SELECT $COL_USER_ID, $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_DATE, $COL_TYPE, $COL_MESSAGE_STATUS, $COL_MESSAGE_ID FROM $INGOING_TABLE_NAME" "SELECT $COL_CHAT_ID, $COL_LAT, $COL_LON, $COL_ALTITUDE, $COL_SPEED, $COL_HDOP, $COL_BEARING, $COL_TIME, $COL_TYPE, $COL_MESSAGE_STATUS FROM $BUFFER_TABLE_NAME"
private const val INGOING_TABLE_CLEAR = "DELETE FROM $INGOING_TABLE_NAME" private const val BUFFER_TABLE_CLEAR = "DELETE FROM $BUFFER_TABLE_NAME"
private const val INGOING_TABLE_DELETE = "DROP TABLE IF EXISTS $INGOING_TABLE_NAME" private const val BUFFER_TABLE_DELETE = "DROP TABLE IF EXISTS $BUFFER_TABLE_NAME"
} }
} }
data class LocationMessage( data class LocationMessage(
val userId: Int, val userId: Int,
val chatId: Long,
val lat: Double,
val lon: Double,
val altitude: Double,
val speed: Double,
val hdop: Double,
val bearing: Double,
val date: Long,
val type: Int)
data class BufferMessage (
val chatId: Long, val chatId: Long,
val lat: Double, val lat: Double,
val lon: Double, val lon: Double,
@ -211,20 +249,18 @@ class LocationMessages(val app: TelegramApplication) {
val date: Long, val date: Long,
val type: Int, val type: Int,
// todo - status and messageId should be updated in db right away. Make them val instead of var. // todo - status and messageId should be updated in db right away. Make them val instead of var.
var status: Int, val status: Int)
var messageId: Long) {
companion object { companion object {
const val STATUS_PREPARED = 0 const val STATUS_PREPARED = 0
const val STATUS_PENDING = 1 const val STATUS_PENDING = 1
const val STATUS_SENT = 2 const val STATUS_SENT = 2
const val STATUS_ERROR = 3 const val STATUS_ERROR = 3
const val TYPE_USER_MAP = 0 const val TYPE_USER_MAP = 0
const val TYPE_USER_TEXT = 1 const val TYPE_USER_TEXT = 1
const val TYPE_BOT_MAP = 2 const val TYPE_BOT_MAP = 2
const val TYPE_BOT_TEXT = 3 const val TYPE_BOT_TEXT = 3
}
} }
} }

View file

@ -3,7 +3,7 @@ package net.osmand.telegram.helpers
import net.osmand.Location import net.osmand.Location
import net.osmand.PlatformUtil import net.osmand.PlatformUtil
import net.osmand.telegram.* import net.osmand.telegram.*
import net.osmand.telegram.helpers.LocationMessages.LocationMessage import net.osmand.telegram.helpers.LocationMessages.BufferMessage
import net.osmand.telegram.notifications.TelegramNotification.NotificationType import net.osmand.telegram.notifications.TelegramNotification.NotificationType
import net.osmand.telegram.utils.AndroidNetworkUtils import net.osmand.telegram.utils.AndroidNetworkUtils
import net.osmand.telegram.utils.BASE_URL import net.osmand.telegram.utils.BASE_URL
@ -50,8 +50,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
if (location != null) { if (location != null) {
if (app.settings.getChatsShareInfo().isNotEmpty()) { if (app.settings.getChatsShareInfo().isNotEmpty()) {
addNewLocationMessages(location, app.telegramHelper.getCurrentUserId()) shareLocationMessages(location, app.telegramHelper.getCurrentUserId())
shareMessages()
} }
lastLocationMessageSentTime = System.currentTimeMillis() lastLocationMessageSentTime = System.currentTimeMillis()
} }
@ -132,58 +131,45 @@ class ShareLocationHelper(private val app: TelegramApplication) {
refreshNotification() refreshNotification()
} }
private fun addNewLocationMessages(location: Location, userId: Int) { private fun shareLocationMessages(location: Location, userId: Int) {
val chatsShareInfo = app.settings.getChatsShareInfo() val chatsShareInfo = app.settings.getChatsShareInfo()
val latitude = location.latitude val latitude = location.latitude
val longitude = location.longitude val longitude = location.longitude
val isBot = app.settings.currentSharingMode != userId.toString() val sharingMode = app.settings.currentSharingMode
val isBot = sharingMode != userId.toString()
val types = mutableListOf<Int>() val types = mutableListOf<Int>()
var bufferedMessagesFull = false
when (app.settings.shareTypeValue) { when (app.settings.shareTypeValue) {
SHARE_TYPE_MAP -> { SHARE_TYPE_MAP -> {
types.add(if (isBot) LocationMessage.TYPE_BOT_MAP else LocationMessage.TYPE_USER_MAP) types.add(if (isBot) LocationMessages.TYPE_BOT_MAP else LocationMessages.TYPE_USER_MAP)
} }
SHARE_TYPE_TEXT -> { SHARE_TYPE_TEXT -> {
types.add(if (isBot) LocationMessage.TYPE_BOT_TEXT else LocationMessage.TYPE_USER_TEXT) types.add(if (isBot) LocationMessages.TYPE_BOT_TEXT else LocationMessages.TYPE_USER_TEXT)
} }
SHARE_TYPE_MAP_AND_TEXT -> { SHARE_TYPE_MAP_AND_TEXT -> {
types.add(if (isBot) LocationMessage.TYPE_BOT_MAP else LocationMessage.TYPE_USER_MAP) types.add(if (isBot) LocationMessages.TYPE_BOT_MAP else LocationMessages.TYPE_USER_MAP)
types.add(if (isBot) LocationMessage.TYPE_BOT_TEXT else LocationMessage.TYPE_USER_TEXT) types.add(if (isBot) LocationMessages.TYPE_BOT_TEXT else LocationMessages.TYPE_USER_TEXT)
} }
} }
chatsShareInfo.values.forEach { shareInfo -> chatsShareInfo.values.forEach { shareInfo ->
types.forEach { if (shareInfo.pendingTdLib >= 10) {
val message = LocationMessage(userId, shareInfo.chatId, latitude, longitude, location.altitude, location.speed.toDouble(), bufferedMessagesFull = true
location.accuracy.toDouble(), location.bearing.toDouble(), location.time, it, LocationMessage.STATUS_PREPARED, shareInfo.currentMapMessageId)
app.locationMessages.addOutgoingMessage(message)
} }
} types.forEach {
} val message = BufferMessage(shareInfo.chatId, latitude, longitude, location.altitude, location.speed.toDouble(),
location.accuracy.toDouble(), location.bearing.toDouble(), location.time, it, LocationMessages.STATUS_PREPARED)
private fun shareMessages() { when (app.settings.shareTypeValue) {
var bufferedMessagesFull = false SHARE_TYPE_MAP -> {
app.locationMessages.getPreparedMessages().forEach { prepareMapMessage(shareInfo, message, isBot, sharingMode)
val shareChatInfo = app.settings.getChatsShareInfo()[it.chatId] }
if (shareChatInfo != null) { SHARE_TYPE_TEXT -> {
bufferedMessagesFull = shareChatInfo.bufferedMessages < 10 prepareTextMessage(shareInfo, message, isBot, sharingMode)
if (bufferedMessagesFull) { }
when { SHARE_TYPE_MAP_AND_TEXT -> {
it.type == LocationMessage.TYPE_USER_TEXT -> { prepareMapMessage(shareInfo, message, isBot, sharingMode)
shareChatInfo.bufferedMessages++ prepareTextMessage(shareInfo, message, isBot, sharingMode)
it.status = LocationMessage.STATUS_PENDING
app.telegramHelper.sendLiveLocationText(shareChatInfo, it)
}
it.type == LocationMessage.TYPE_USER_MAP -> {
shareChatInfo.bufferedMessages++
it.status = LocationMessage.STATUS_PENDING
app.telegramHelper.sendLiveLocationMap(shareChatInfo, it)
}
it.type == LocationMessage.TYPE_BOT_TEXT -> {
sendLocationToBot(it, app.settings.currentSharingMode, shareChatInfo, SHARE_TYPE_TEXT)
}
it.type == LocationMessage.TYPE_BOT_MAP -> {
sendLocationToBot(it, app.settings.currentSharingMode, shareChatInfo, SHARE_TYPE_MAP)
}
} }
} }
} }
@ -193,6 +179,58 @@ class ShareLocationHelper(private val app: TelegramApplication) {
} }
} }
private fun prepareTextMessage(shareInfo: TelegramSettings.ShareChatInfo,message: BufferMessage,isBot:Boolean, sharingMode: String) {
if (shareInfo.currentTextMessageId == -1L) {
if (shareInfo.pendingTextMessage) {
app.locationMessages.addBufferedMessage(message)
} else {
if (isBot) {
sendLocationToBot(message, sharingMode, shareInfo, SHARE_TYPE_TEXT)
} else {
shareInfo.pendingTdLib++
app.telegramHelper.sendNewTextLocation(shareInfo, message)
}
}
} else {
if (isBot) {
sendLocationToBot(message, sharingMode, shareInfo, SHARE_TYPE_TEXT)
} else {
if (shareInfo.pendingTdLib < 10) {
shareInfo.pendingTdLib++
app.telegramHelper.editTextLocation(shareInfo, message)
} else {
app.locationMessages.addBufferedMessage(message)
}
}
}
}
private fun prepareMapMessage(shareInfo: TelegramSettings.ShareChatInfo,message: BufferMessage,isBot:Boolean, sharingMode: String) {
if (shareInfo.currentMapMessageId == -1L) {
if (shareInfo.pendingMapMessage) {
app.locationMessages.addBufferedMessage(message)
} else {
if (isBot) {
sendLocationToBot(message, sharingMode, shareInfo, SHARE_TYPE_MAP)
} else {
shareInfo.pendingTdLib++
app.telegramHelper.sendNewMapLocation(shareInfo, message)
}
}
} else {
if (isBot) {
sendLocationToBot(message, sharingMode, shareInfo, SHARE_TYPE_MAP)
} else {
if (shareInfo.pendingTdLib < 10) {
shareInfo.pendingTdLib++
app.telegramHelper.editMapLocation(shareInfo, message)
} else {
app.locationMessages.addBufferedMessage(message)
}
}
}
}
private fun checkNetworkType(){ private fun checkNetworkType(){
if (app.isInternetConnectionAvailable) { if (app.isInternetConnectionAvailable) {
val networkType = when { val networkType = when {
@ -204,9 +242,9 @@ class ShareLocationHelper(private val app: TelegramApplication) {
} }
} }
private fun sendLocationToBot(locationMessage: LocationMessage, sharingMode: String, shareInfo: TelegramSettings.ShareChatInfo, shareType: String) { private fun sendLocationToBot(locationMessage: BufferMessage, sharingMode: String, shareInfo: TelegramSettings.ShareChatInfo, shareType: String) {
if (app.isInternetConnectionAvailable) { if (app.isInternetConnectionAvailable) {
locationMessage.status = LocationMessage.STATUS_PENDING // locationMessage.status = LocationMessage.STATUS_PENDING
val url = getDeviceSharingUrl(locationMessage, sharingMode) val url = getDeviceSharingUrl(locationMessage, sharingMode)
AndroidNetworkUtils.sendRequestAsync(app, url, null, "Send Location", false, false, AndroidNetworkUtils.sendRequestAsync(app, url, null, "Send Location", false, false,
object : AndroidNetworkUtils.OnRequestResultListener { object : AndroidNetworkUtils.OnRequestResultListener {
@ -216,7 +254,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
val osmandBotId = app.telegramHelper.getOsmandBot()?.id ?: -1 val osmandBotId = app.telegramHelper.getOsmandBot()?.id ?: -1
val device = app.settings.getCurrentSharingDevice() val device = app.settings.getCurrentSharingDevice()
locationMessage.status = if (success) LocationMessage.STATUS_SENT else LocationMessage.STATUS_ERROR // locationMessage.status = if (success) LocationMessage.STATUS_SENT else LocationMessage.STATUS_ERROR
if (success && shareInfo.shouldSendViaBotMessage && osmandBotId != -1 && device != null) { if (success && shareInfo.shouldSendViaBotMessage && osmandBotId != -1 && device != null) {
app.telegramHelper.sendViaBotLocationMessage(osmandBotId, shareInfo, TdApi.Location(locationMessage.lat, locationMessage.lon), device, shareType) app.telegramHelper.sendViaBotLocationMessage(osmandBotId, shareInfo, TdApi.Location(locationMessage.lat, locationMessage.lon), device, shareType)
shareInfo.shouldSendViaBotMessage = false shareInfo.shouldSendViaBotMessage = false
@ -226,7 +264,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
} }
} }
private fun getDeviceSharingUrl(loc: LocationMessage, sharingMode: String): String { private fun getDeviceSharingUrl(loc: BufferMessage, sharingMode: String): String {
val url = "$BASE_URL/device/$sharingMode/send?lat=${loc.lat}&lon=${loc.lon}" val url = "$BASE_URL/device/$sharingMode/send?lat=${loc.lat}&lon=${loc.lon}"
val builder = StringBuilder(url) val builder = StringBuilder(url)
if (loc.bearing != 0.0) { if (loc.bearing != 0.0) {

View file

@ -761,27 +761,6 @@ class TelegramHelper private constructor() {
} }
} }
/**
* @chatId Id of the chat
* @livePeriod Period for which the location can be updated, in seconds; should be between 60 and 86400 for a live location and 0 otherwise.
* @latitude Latitude of the location
* @longitude Longitude of the location
*/
fun sendLiveLocationMessage(chatsShareInfo:Map<Long, TelegramSettings.ShareChatInfo>, latitude: Double, longitude: Double): Boolean {
if (!requestingActiveLiveLocationMessages && haveAuthorization) {
if (needRefreshActiveLiveLocationMessages) {
getActiveLiveLocationMessages {
sendLiveLocationImpl(chatsShareInfo, latitude, longitude)
}
needRefreshActiveLiveLocationMessages = false
} else {
sendLiveLocationImpl(chatsShareInfo, latitude, longitude)
}
return true
}
return false
}
fun stopSendingLiveLocationToChat(shareInfo: TelegramSettings.ShareChatInfo) { fun stopSendingLiveLocationToChat(shareInfo: TelegramSettings.ShareChatInfo) {
if (shareInfo.currentMapMessageId != -1L && shareInfo.chatId != -1L) { if (shareInfo.currentMapMessageId != -1L && shareInfo.chatId != -1L) {
client?.send( client?.send(
@ -831,7 +810,7 @@ class TelegramHelper private constructor() {
private fun recreateLiveLocationMessage( private fun recreateLiveLocationMessage(
shareInfo: TelegramSettings.ShareChatInfo, shareInfo: TelegramSettings.ShareChatInfo,
content: TdApi.InputMessageContent,locationMessage: LocationMessages.LocationMessage? content: TdApi.InputMessageContent,locationMessage: LocationMessages.BufferMessage?
) { ) {
if (shareInfo.chatId != -1L) { if (shareInfo.chatId != -1L) {
val array = LongArray(1) val array = LongArray(1)
@ -861,106 +840,68 @@ class TelegramHelper private constructor() {
needRefreshActiveLiveLocationMessages = true needRefreshActiveLiveLocationMessages = true
} }
private fun sendNewLiveLocationMessage(shareInfo: TelegramSettings.ShareChatInfo, content: TdApi.InputMessageContent, locationMessage: LocationMessages.LocationMessage?) { private fun sendNewLiveLocationMessage(shareInfo: TelegramSettings.ShareChatInfo, content: TdApi.InputMessageContent, locationMessage: LocationMessages.BufferMessage?) {
needRefreshActiveLiveLocationMessages = true needRefreshActiveLiveLocationMessages = true
log.debug("sendNewLiveLocationMessage") log.debug("sendNewLiveLocationMessage")
client?.send( client?.send(TdApi.SendMessage(shareInfo.chatId, 0, false, true, null, content)) { obj ->
TdApi.SendMessage(shareInfo.chatId, 0, false, true, null, content)) { obj -> if (locationMessage?.type == LocationMessages.TYPE_USER_TEXT || locationMessage?.type == LocationMessages.TYPE_BOT_TEXT) {
handleMapLocationMessageUpdate(obj, shareInfo, locationMessage) handleTextLocationMessageUpdate(obj, shareInfo, locationMessage)
} } else if (locationMessage?.type == LocationMessages.TYPE_USER_MAP || locationMessage?.type == LocationMessages.TYPE_BOT_MAP) {
} handleMapLocationMessageUpdate(obj, shareInfo, locationMessage)
private fun sendLiveLocationImpl(chatsShareInfo: Map<Long, TelegramSettings.ShareChatInfo>, latitude: Double, longitude: Double) {
val location = TdApi.Location(latitude, longitude)
chatsShareInfo.forEach { (chatId, shareInfo) ->
if (shareInfo.getChatLiveMessageExpireTime() <= 0) {
return@forEach
}
val livePeriod =
if (shareInfo.currentMessageLimit > (shareInfo.start + MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC)) {
MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC
} else {
shareInfo.livePeriod.toInt()
}
val content = TdApi.InputMessageLocation(location, livePeriod)
val msgId = shareInfo.currentMapMessageId
val timeAfterLastSendMessage = ((System.currentTimeMillis() / 1000) - shareInfo.lastSendMapMessageTime)
log.debug("sendLiveLocationImpl - $msgId pendingMapMessage ${shareInfo.pendingMapMessage}")
if (msgId != -1L) {
if (shareInfo.shouldDeletePreviousMapMessage) {
recreateLiveLocationMessage(shareInfo, content, null)
shareInfo.shouldDeletePreviousMapMessage = false
shareInfo.currentMapMessageId = -1
} else {
log.debug("EditMessageLiveLocation - $msgId")
client?.send(
TdApi.EditMessageLiveLocation(chatId, msgId, null, location)) { obj ->
handleMapLocationMessageUpdate(obj, shareInfo, null)
}
}
} else if (!shareInfo.pendingMapMessage || shareInfo.pendingMapMessage && timeAfterLastSendMessage > SEND_NEW_MESSAGE_INTERVAL_SEC) {
sendNewLiveLocationMessage(shareInfo, content, null)
} }
} }
} }
fun sendLiveLocationMap(shareInfo: TelegramSettings.ShareChatInfo, locationMessage: LocationMessages.LocationMessage) { fun sendNewTextLocation(shareInfo: TelegramSettings.ShareChatInfo, location: LocationMessages.BufferMessage) {
shareInfo.updateTextMessageId = 1
val content = OsmandLocationUtils.getTextMessageContent(shareInfo.updateTextMessageId, location)
if (!shareInfo.pendingTextMessage) {
shareInfo.pendingTextMessage = true
client?.send(TdApi.SendMessage(shareInfo.chatId, 0, false, true, null, content)) { obj ->
handleTextLocationMessageUpdate(obj, shareInfo, location)
}
}
}
fun editTextLocation(shareInfo: TelegramSettings.ShareChatInfo, location: LocationMessages.BufferMessage) {
val content = OsmandLocationUtils.getTextMessageContent(shareInfo.updateTextMessageId, location)
if (shareInfo.currentTextMessageId!=-1L) {
client?.send(TdApi.EditMessageText(shareInfo.chatId, shareInfo.currentTextMessageId, null, content)) { obj ->
handleTextLocationMessageUpdate(obj, shareInfo, location)
}
}
}
fun sendNewMapLocation(shareInfo: TelegramSettings.ShareChatInfo, locationMessage: LocationMessages.BufferMessage) {
needRefreshActiveLiveLocationMessages = true
val location = TdApi.Location(locationMessage.lat, locationMessage.lon) val location = TdApi.Location(locationMessage.lat, locationMessage.lon)
val livePeriod = if (shareInfo.currentMessageLimit > (shareInfo.start + MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC)) { val livePeriod =
if (shareInfo.currentMessageLimit > (shareInfo.start + MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC)) {
MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC
} else { } else {
shareInfo.livePeriod.toInt() shareInfo.livePeriod.toInt()
} }
val content = TdApi.InputMessageLocation(location, livePeriod) val content = TdApi.InputMessageLocation(location, livePeriod)
val msgId = shareInfo.currentMapMessageId if (!shareInfo.pendingMapMessage) {
val timeAfterLastSendMessage = ((System.currentTimeMillis() / 1000) - shareInfo.lastSendMapMessageTime) shareInfo.pendingMapMessage = true
log.debug("sendLiveLocationImpl - $msgId pendingMapMessage ${shareInfo.pendingMapMessage}") client?.send(TdApi.SendMessage(shareInfo.chatId, 0, false, true, null, content)) { obj ->
if (msgId != -1L) { handleMapLocationMessageUpdate(obj, shareInfo, locationMessage)
if (shareInfo.shouldDeletePreviousMapMessage) {
recreateLiveLocationMessage(shareInfo, content, locationMessage)
shareInfo.shouldDeletePreviousMapMessage = false
shareInfo.currentMapMessageId = -1
} else {
log.debug("EditMessageLiveLocation - $msgId")
client?.send(
TdApi.EditMessageLiveLocation(shareInfo.chatId, msgId, null, location)) { obj ->
handleMapLocationMessageUpdate(obj, shareInfo, locationMessage)
}
}
} else if (!shareInfo.pendingMapMessage || shareInfo.pendingMapMessage && timeAfterLastSendMessage > SEND_NEW_MESSAGE_INTERVAL_SEC) {
sendNewLiveLocationMessage(shareInfo, content, locationMessage)
}
}
fun sendLiveLocationText(shareInfo: TelegramSettings.ShareChatInfo, location: LocationMessages.LocationMessage) {
val msgId = shareInfo.currentTextMessageId
if (msgId == -1L) {
shareInfo.updateTextMessageId = 1
}
val content = OsmandLocationUtils.getTextMessageContent(shareInfo.updateTextMessageId, location)
val timeAfterLastSendMessage = ((System.currentTimeMillis() / 1000) - shareInfo.lastSendTextMessageTime)
log.debug("sendLiveLocationText - $msgId pendingMapMessage ${shareInfo.pendingTextMessage}")
if (msgId != -1L) {
if (shareInfo.shouldDeletePreviousTextMessage) {
recreateLiveLocationMessage(shareInfo, content, location)
shareInfo.shouldDeletePreviousTextMessage = false
} else {
client?.send(TdApi.EditMessageText(shareInfo.chatId, msgId, null, content)) { obj ->
handleTextLocationMessageUpdate(obj, shareInfo, location)
}
}
} else {
if (!shareInfo.pendingTextMessage) {
client?.send(TdApi.SendMessage(shareInfo.chatId, 0, false, false, null, content)) { obj ->
handleTextLocationMessageUpdate(obj, shareInfo, location)
}
} else if(timeAfterLastSendMessage > SEND_NEW_MESSAGE_INTERVAL_SEC){
} }
} }
} }
private fun handleMapLocationMessageUpdate(obj: TdApi.Object, shareInfo: TelegramSettings.ShareChatInfo, location: LocationMessages.LocationMessage?) { fun editMapLocation(shareInfo: TelegramSettings.ShareChatInfo, locationMessage: LocationMessages.BufferMessage) {
needRefreshActiveLiveLocationMessages = true
val location = TdApi.Location(locationMessage.lat, locationMessage.lon)
if (shareInfo.currentMapMessageId!=-1L) {
client?.send(
TdApi.EditMessageLiveLocation(shareInfo.chatId, shareInfo.currentMapMessageId, null, location)) { obj ->
handleMapLocationMessageUpdate(obj, shareInfo, locationMessage)
}
}
}
private fun handleMapLocationMessageUpdate(obj: TdApi.Object, shareInfo: TelegramSettings.ShareChatInfo, location: LocationMessages.BufferMessage?) {
when (obj.constructor) { when (obj.constructor) {
TdApi.Error.CONSTRUCTOR -> { TdApi.Error.CONSTRUCTOR -> {
val error = obj as TdApi.Error val error = obj as TdApi.Error
@ -980,7 +921,8 @@ class TelegramHelper private constructor() {
obj.sendingState?.constructor == TdApi.MessageSendingStateFailed.CONSTRUCTOR -> { obj.sendingState?.constructor == TdApi.MessageSendingStateFailed.CONSTRUCTOR -> {
shareInfo.hasSharingError = true shareInfo.hasSharingError = true
needRefreshActiveLiveLocationMessages = true needRefreshActiveLiveLocationMessages = true
location?.status = LocationMessages.LocationMessage.STATUS_ERROR shareInfo.pendingMapMessage = false
// location?.status = LocationMessages.LocationMessage.STATUS_ERROR
outgoingMessagesListeners.forEach { outgoingMessagesListeners.forEach {
it.onSendLiveLocationError(-1, "Map location message ${obj.id} failed to send") it.onSendLiveLocationError(-1, "Map location message ${obj.id} failed to send")
} }
@ -988,14 +930,15 @@ class TelegramHelper private constructor() {
obj.sendingState?.constructor == TdApi.MessageSendingStatePending.CONSTRUCTOR -> { obj.sendingState?.constructor == TdApi.MessageSendingStatePending.CONSTRUCTOR -> {
shareInfo.pendingMapMessage = true shareInfo.pendingMapMessage = true
shareInfo.lastSendMapMessageTime = obj.date shareInfo.lastSendMapMessageTime = obj.date
location?.status = LocationMessages.LocationMessage.STATUS_PENDING // location?.status = LocationMessages.LocationMessage.STATUS_PENDING
log.debug("handleMapLocationMessageUpdate - MessageSendingStatePending") log.debug("handleMapLocationMessageUpdate - MessageSendingStatePending")
} }
else -> { else -> {
shareInfo.hasSharingError = false shareInfo.hasSharingError = false
shareInfo.bufferedMessages-- shareInfo.pendingTdLib--
location?.messageId = obj.id shareInfo.pendingMapMessage = false
location?.status = LocationMessages.LocationMessage.STATUS_SENT // location?.messageId = obj.id
// location?.status = LocationMessages.LocationMessage.STATUS_SENT
outgoingMessagesListeners.forEach { outgoingMessagesListeners.forEach {
it.onUpdateMessages(listOf(obj)) it.onUpdateMessages(listOf(obj))
} }
@ -1006,7 +949,7 @@ class TelegramHelper private constructor() {
} }
} }
private fun handleTextLocationMessageUpdate(obj: TdApi.Object, shareInfo: TelegramSettings.ShareChatInfo, location: LocationMessages.LocationMessage?) { private fun handleTextLocationMessageUpdate(obj: TdApi.Object, shareInfo: TelegramSettings.ShareChatInfo, location: LocationMessages.BufferMessage?) {
when (obj.constructor) { when (obj.constructor) {
TdApi.Error.CONSTRUCTOR -> { TdApi.Error.CONSTRUCTOR -> {
val error = obj as TdApi.Error val error = obj as TdApi.Error
@ -1024,9 +967,10 @@ class TelegramHelper private constructor() {
when { when {
obj.sendingState?.constructor == TdApi.MessageSendingStateFailed.CONSTRUCTOR -> { obj.sendingState?.constructor == TdApi.MessageSendingStateFailed.CONSTRUCTOR -> {
shareInfo.hasSharingError = true shareInfo.hasSharingError = true
shareInfo.bufferedMessages-- shareInfo.pendingTdLib--
shareInfo.pendingTextMessage = false
needRefreshActiveLiveLocationMessages = true needRefreshActiveLiveLocationMessages = true
location?.status = LocationMessages.LocationMessage.STATUS_ERROR // location?.status = LocationMessages.LocationMessage.STATUS_ERROR
outgoingMessagesListeners.forEach { outgoingMessagesListeners.forEach {
it.onSendLiveLocationError(-1, "Text location message ${obj.id} failed to send") it.onSendLiveLocationError(-1, "Text location message ${obj.id} failed to send")
} }
@ -1034,14 +978,15 @@ class TelegramHelper private constructor() {
obj.sendingState?.constructor == TdApi.MessageSendingStatePending.CONSTRUCTOR -> { obj.sendingState?.constructor == TdApi.MessageSendingStatePending.CONSTRUCTOR -> {
shareInfo.pendingTextMessage = true shareInfo.pendingTextMessage = true
shareInfo.lastSendTextMessageTime = obj.date shareInfo.lastSendTextMessageTime = obj.date
location?.status = LocationMessages.LocationMessage.STATUS_PENDING // location?.status = LocationMessages.LocationMessage.STATUS_PENDING
log.debug("handleTextLocationMessageUpdate - MessageSendingStatePending") log.debug("handleTextLocationMessageUpdate - MessageSendingStatePending")
} }
else -> { else -> {
shareInfo.hasSharingError = false shareInfo.hasSharingError = false
shareInfo.bufferedMessages-- shareInfo.pendingTdLib--
location?.messageId = obj.id shareInfo.pendingTextMessage = false
location?.status = LocationMessages.LocationMessage.STATUS_SENT // location?.messageId = obj.id
// location?.status = LocationMessages.LocationMessage.STATUS_SENT
outgoingMessagesListeners.forEach { outgoingMessagesListeners.forEach {
it.onUpdateMessages(listOf(obj)) it.onUpdateMessages(listOf(obj))
} }

View file

@ -19,6 +19,7 @@ import android.widget.*
import net.osmand.PlatformUtil import net.osmand.PlatformUtil
import net.osmand.telegram.R import net.osmand.telegram.R
import net.osmand.telegram.TelegramApplication import net.osmand.telegram.TelegramApplication
import net.osmand.telegram.helpers.LocationMessages
import net.osmand.telegram.helpers.LocationMessages.LocationMessage import net.osmand.telegram.helpers.LocationMessages.LocationMessage
import net.osmand.telegram.helpers.OsmandAidlHelper import net.osmand.telegram.helpers.OsmandAidlHelper
import net.osmand.telegram.helpers.TelegramHelper import net.osmand.telegram.helpers.TelegramHelper
@ -293,7 +294,7 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
} }
if (app.telegramService == null) { if (app.telegramService == null) {
messages.forEach { messages.forEach {
val locationMessage = OsmandLocationUtils.parseMessage(it, telegramHelper, LocationMessage.STATUS_PREPARED) val locationMessage = OsmandLocationUtils.parseMessage(it, telegramHelper, LocationMessages.STATUS_PREPARED)
if (locationMessage != null) { if (locationMessage != null) {
app.locationMessages.addIngoingMessage(locationMessage) app.locationMessages.addIngoingMessage(locationMessage)
} }
@ -349,8 +350,7 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
fun logoutTelegram(silent: Boolean = false) { fun logoutTelegram(silent: Boolean = false) {
if (telegramHelper.getTelegramAuthorizationState() == TelegramHelper.TelegramAuthorizationState.READY) { if (telegramHelper.getTelegramAuthorizationState() == TelegramHelper.TelegramAuthorizationState.READY) {
if (app.isInternetConnectionAvailable) { if (app.isInternetConnectionAvailable) {
// todo - why delete messages on logout? app.locationMessages.clearBufferedMessages()
app.locationMessages.clearOutgoingMessages()
settings.clear() settings.clear()
telegramHelper.logout() telegramHelper.logout()
} else { } else {

View file

@ -190,22 +190,22 @@ class TimelineTabFragment : Fragment() {
val res = mutableListOf<ListItem>() val res = mutableListOf<ListItem>()
val ignoredUsersIds = ArrayList<Int>() val ignoredUsersIds = ArrayList<Int>()
val currentUserId = telegramHelper.getCurrentUser()?.id val currentUserId = telegramHelper.getCurrentUser()?.id
if (currentUserId != null) { // if (currentUserId != null) {
val locationMessages = app.locationMessages.collectRecordedDataForUser(currentUserId, 0, start, end) // val locationMessages = app.locationMessages.collectRecordedDataForUser(currentUserId, 0, start, end)
// todo - why do we need convert to gpx on update? Is locationMessages not enough to display info? // // todo - why do we need convert to gpx on update? Is locationMessages not enough to display info?
OsmandLocationUtils.convertLocationMessagesToGpxFiles(locationMessages, false).forEach { // OsmandLocationUtils.convertLocationMessagesToGpxFiles(locationMessages, false).forEach {
TelegramUiHelper.gpxToChatItem(telegramHelper, it, true)?.also { chatItem -> // TelegramUiHelper.gpxToChatItem(telegramHelper, it, true)?.also { chatItem ->
res.add(chatItem) // res.add(chatItem)
} // }
} // }
ignoredUsersIds.add(currentUserId) // ignoredUsersIds.add(currentUserId)
} // }
val locationMessages = app.locationMessages.collectRecordedDataForUsers(start, end, ignoredUsersIds) // val locationMessages = app.locationMessages.collectRecordedDataForUsers(start, end, ignoredUsersIds)
OsmandLocationUtils.convertLocationMessagesToGpxFiles(locationMessages).forEach { // OsmandLocationUtils.convertLocationMessagesToGpxFiles(locationMessages).forEach {
TelegramUiHelper.gpxToChatItem(telegramHelper, it,false)?.also { chatItem -> // TelegramUiHelper.gpxToChatItem(telegramHelper, it,false)?.also { chatItem ->
res.add(chatItem) // res.add(chatItem)
} // }
} // }
adapter.items = sortAdapterItems(res) adapter.items = sortAdapterItems(res)
} }

View file

@ -207,14 +207,14 @@ class UserGpxInfoFragment : BaseDialogFragment() {
} }
private fun updateGpxInfo() { private fun updateGpxInfo() {
gpxFile = OsmandLocationUtils.convertLocationMessagesToGpxFiles( // gpxFile = OsmandLocationUtils.convertLocationMessagesToGpxFiles(
app.locationMessages.collectRecordedDataForUser( // app.locationMessages.collectRecordedDataForUser(
gpxFile.userId, // gpxFile.userId,
gpxFile.chatId, // gpxFile.chatId,
startCalendar.timeInMillis, // startCalendar.timeInMillis,
endCalendar.timeInMillis // endCalendar.timeInMillis
) // )
).first() // ).first()
updateGPXStatisticRow() updateGPXStatisticRow()
updateDateAndTimeButtons() updateDateAndTimeButtons()
updateGPXMap() updateGPXMap()

View file

@ -3,7 +3,9 @@ package net.osmand.telegram.utils
import android.os.AsyncTask import android.os.AsyncTask
import net.osmand.Location import net.osmand.Location
import net.osmand.telegram.TelegramApplication import net.osmand.telegram.TelegramApplication
import net.osmand.telegram.helpers.LocationMessages
import net.osmand.telegram.helpers.LocationMessages.LocationMessage import net.osmand.telegram.helpers.LocationMessages.LocationMessage
import net.osmand.telegram.helpers.LocationMessages.BufferMessage
import net.osmand.telegram.helpers.TelegramHelper import net.osmand.telegram.helpers.TelegramHelper
import net.osmand.telegram.helpers.TelegramUiHelper import net.osmand.telegram.helpers.TelegramUiHelper
import net.osmand.util.GeoPointParserUtil import net.osmand.util.GeoPointParserUtil
@ -108,7 +110,7 @@ object OsmandLocationUtils {
if (parsedMessageContent != null) { if (parsedMessageContent != null) {
locationMessage = LocationMessage(helper.getSenderMessageId(message), message.chatId, parsedMessageContent.lat, locationMessage = LocationMessage(helper.getSenderMessageId(message), message.chatId, parsedMessageContent.lat,
parsedMessageContent.lon, parsedMessageContent.altitude, parsedMessageContent.speed, parsedMessageContent.hdop, parsedMessageContent.lon, parsedMessageContent.altitude, parsedMessageContent.speed, parsedMessageContent.hdop,
parsedMessageContent.bearing, parsedMessageContent.lastUpdated * 1000L, messageType, status, message.id) parsedMessageContent.bearing, parsedMessageContent.lastUpdated * 1000L, messageType)
} }
return locationMessage return locationMessage
} }
@ -121,6 +123,10 @@ object OsmandLocationUtils {
return String.format(Locale.US, "%.5f, %.5f", sig.lat, sig.lon) return String.format(Locale.US, "%.5f, %.5f", sig.lat, sig.lon)
} }
fun formatLocation(sig: BufferMessage): String {
return String.format(Locale.US, "%.5f, %.5f", sig.lat, sig.lon)
}
fun formatFullTime(ti: Long): String { fun formatFullTime(ti: Long): String {
val dt = Date(ti) val dt = Date(ti)
return UTC_DATE_FORMAT.format(dt) + " " + UTC_TIME_FORMAT.format(dt) + " UTC" return UTC_DATE_FORMAT.format(dt) + " " + UTC_TIME_FORMAT.format(dt) + " UTC"
@ -313,6 +319,45 @@ object OsmandLocationUtils {
return TdApi.InputMessageText(TdApi.FormattedText(textMessage, entities.toTypedArray()), true, true) return TdApi.InputMessageText(TdApi.FormattedText(textMessage, entities.toTypedArray()), true, true)
} }
fun getTextMessageContent(updateId: Int, location: BufferMessage): TdApi.InputMessageText {
val entities = mutableListOf<TdApi.TextEntity>()
val builder = StringBuilder()
val locationMessage = formatLocation(location)
val firstSpace = USER_TEXT_LOCATION_TITLE.indexOf(' ')
val secondSpace = USER_TEXT_LOCATION_TITLE.indexOf(' ', firstSpace + 1)
entities.add(TdApi.TextEntity(builder.length + firstSpace + 1, secondSpace - firstSpace, TdApi.TextEntityTypeTextUrl(SHARING_LINK)))
builder.append("$USER_TEXT_LOCATION_TITLE\n")
entities.add(TdApi.TextEntity(builder.lastIndex, LOCATION_PREFIX.length, TdApi.TextEntityTypeBold()))
builder.append(LOCATION_PREFIX)
entities.add(TdApi.TextEntity(builder.length, locationMessage.length,
TdApi.TextEntityTypeTextUrl("$BASE_SHARING_URL?lat=${location.lat}&lon=${location.lon}")))
builder.append("$locationMessage\n")
if (location.altitude != 0.0) {
entities.add(TdApi.TextEntity(builder.lastIndex, ALTITUDE_PREFIX.length, TdApi.TextEntityTypeBold()))
builder.append(String.format(Locale.US, "$ALTITUDE_PREFIX%.1f m\n", location.altitude))
}
if (location.speed > 0) {
entities.add(TdApi.TextEntity(builder.lastIndex, SPEED_PREFIX.length, TdApi.TextEntityTypeBold()))
builder.append(String.format(Locale.US, "$SPEED_PREFIX%.1f m/s\n", location.speed))
}
if (location.hdop != 0.0 && location.speed == 0.0) {
entities.add(TdApi.TextEntity(builder.lastIndex, HDOP_PREFIX.length, TdApi.TextEntityTypeBold()))
builder.append(String.format(Locale.US, "$HDOP_PREFIX%d m\n", location.hdop.toInt()))
}
if (updateId == 0) {
builder.append(String.format("$UPDATED_PREFIX%s\n", formatFullTime(location.date)))
} else {
builder.append(String.format("$UPDATED_PREFIX%s (%d)\n", formatFullTime(location.date), updateId))
}
val textMessage = builder.toString().trim()
return TdApi.InputMessageText(TdApi.FormattedText(textMessage, entities.toTypedArray()), true, true)
}
fun convertLocationMessagesToGpxFiles(items: List<LocationMessage>, newGpxPerChat: Boolean = true): List<GPXUtilities.GPXFile> { fun convertLocationMessagesToGpxFiles(items: List<LocationMessage>, newGpxPerChat: Boolean = true): List<GPXUtilities.GPXFile> {
val dataTracks = ArrayList<GPXUtilities.GPXFile>() val dataTracks = ArrayList<GPXUtilities.GPXFile>()