Merge pull request #6500 from osmandapp/TelegramDataBase
Telegram improvements
This commit is contained in:
commit
5daac573a1
13 changed files with 300 additions and 131 deletions
|
@ -277,7 +277,9 @@ 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 {
|
||||||
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().settings.updateShareInfo(it)
|
||||||
app().shareLocationHelper.checkAndSendBufferMessagesToChat(it.chatId)
|
app().shareLocationHelper.checkAndSendBufferMessagesToChat(it.chatId)
|
||||||
if (it.sendingState == null && (it.content is TdApi.MessageLocation || it.content is TdApi.MessageText)) {
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -360,7 +360,7 @@ class TelegramSettings(private val app: TelegramApplication) {
|
||||||
if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
|
if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
|
||||||
val loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER)
|
val loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER)
|
||||||
val gpsActive = loc != null && ((statusChangeTime - loc.time) / 1000) < GPS_UPDATE_EXPIRED_TIME
|
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)
|
(gpsActive || !lastSentLocationExpired)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -393,7 +393,7 @@ class TelegramSettings(private val app: TelegramApplication) {
|
||||||
} else if (!initializing) {
|
} else if (!initializing) {
|
||||||
when {
|
when {
|
||||||
!gpsEnabled -> {
|
!gpsEnabled -> {
|
||||||
locationTime = app.shareLocationHelper.lastLocationMessageSentTime
|
locationTime = app.shareLocationHelper.lastLocationUpdateTime
|
||||||
if (locationTime <= 0) {
|
if (locationTime <= 0) {
|
||||||
locationTime = getLastSuccessfulSendTime()
|
locationTime = getLastSuccessfulSendTime()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,19 +4,21 @@ import android.content.Context
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.database.sqlite.SQLiteDatabase
|
import android.database.sqlite.SQLiteDatabase
|
||||||
import android.database.sqlite.SQLiteOpenHelper
|
import android.database.sqlite.SQLiteOpenHelper
|
||||||
|
import net.osmand.Location
|
||||||
import net.osmand.PlatformUtil
|
import net.osmand.PlatformUtil
|
||||||
|
import net.osmand.data.LatLon
|
||||||
import net.osmand.telegram.TelegramApplication
|
import net.osmand.telegram.TelegramApplication
|
||||||
import net.osmand.telegram.utils.OsmandLocationUtils
|
import net.osmand.telegram.utils.OsmandLocationUtils
|
||||||
|
import net.osmand.util.MapUtils
|
||||||
import org.drinkless.td.libcore.telegram.TdApi
|
import org.drinkless.td.libcore.telegram.TdApi
|
||||||
|
|
||||||
class LocationMessages(val app: TelegramApplication) {
|
class LocationMessages(val app: TelegramApplication) {
|
||||||
|
|
||||||
private val log = PlatformUtil.getLog(LocationMessages::class.java)
|
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<BufferMessage>()
|
private var bufferedMessages = emptyList<BufferMessage>()
|
||||||
|
|
||||||
private var lastMessages = emptyList<LocationMessage>()
|
private var lastLocationPoints = mutableMapOf<LocationHistoryPoint, LatLon>()
|
||||||
|
|
||||||
private val dbHelper: SQLiteHelper
|
private val dbHelper: SQLiteHelper
|
||||||
|
|
||||||
|
@ -33,11 +35,14 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
return bufferedMessages.filter { it.chatId==chatId }.sortedBy { it.time }
|
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<LocationMessage> {
|
fun getIngoingMessages(currentUserId: Int, start: Long, end: Long): List<LocationMessage> {
|
||||||
return dbHelper.getIngoingMessages(currentUserId, start, end)
|
return dbHelper.getIngoingMessages(currentUserId, start, end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getIngoingUserLocations(currentUserId: Int, start: Long, end: Long): List<UserLocations> {
|
||||||
|
return dbHelper.getIngoingUserLocations(currentUserId, start, end)
|
||||||
|
}
|
||||||
|
|
||||||
fun getMessagesForUserInChat(userId: Int, chatId: Long, start: Long, end: Long): List<LocationMessage> {
|
fun getMessagesForUserInChat(userId: Int, chatId: Long, start: Long, end: Long): List<LocationMessage> {
|
||||||
return dbHelper.getMessagesForUserInChat(userId, chatId, start, end)
|
return dbHelper.getMessagesForUserInChat(userId, chatId, start, end)
|
||||||
}
|
}
|
||||||
|
@ -46,6 +51,10 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
return dbHelper.getMessagesForUser(userId, start, end)
|
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) {
|
fun addBufferedMessage(message: BufferMessage) {
|
||||||
log.debug("addBufferedMessage $message")
|
log.debug("addBufferedMessage $message")
|
||||||
val messages = mutableListOf(*this.bufferedMessages.toTypedArray())
|
val messages = mutableListOf(*this.bufferedMessages.toTypedArray())
|
||||||
|
@ -58,17 +67,28 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
log.debug("addNewLocationMessage ${message.id}")
|
log.debug("addNewLocationMessage ${message.id}")
|
||||||
val type = OsmandLocationUtils.getMessageType(message, app.telegramHelper)
|
val type = OsmandLocationUtils.getMessageType(message, app.telegramHelper)
|
||||||
|
|
||||||
val previousMessage = lastMessages.firstOrNull { it.chatId == message.chatId && it.userId == message.senderUserId && it.type == type }
|
val newItem = LocationHistoryPoint(message.senderUserId, message.chatId, type)
|
||||||
val locationMessage = OsmandLocationUtils.parseMessage(message, app.telegramHelper, previousMessage)
|
val previousMessageLatLon = lastLocationPoints[newItem]
|
||||||
|
val locationMessage = OsmandLocationUtils.parseMessage(message, app.telegramHelper, previousMessageLatLon)
|
||||||
if (locationMessage != null) {
|
if (locationMessage != null) {
|
||||||
dbHelper.addLocationMessage(locationMessage)
|
dbHelper.addLocationMessage(locationMessage)
|
||||||
val messages = mutableListOf(*this.lastMessages.toTypedArray())
|
lastLocationPoints[newItem] = LatLon(locationMessage.lat, locationMessage.lon)
|
||||||
messages.remove(previousMessage)
|
|
||||||
messages.add(locationMessage)
|
|
||||||
this.lastMessages = messages
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
fun clearBufferedMessages() {
|
||||||
log.debug("clearBufferedMessages")
|
log.debug("clearBufferedMessages")
|
||||||
dbHelper.clearBufferedMessages()
|
dbHelper.clearBufferedMessages()
|
||||||
|
@ -88,7 +108,7 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readLastMessages() {
|
private fun readLastMessages() {
|
||||||
this.lastMessages = dbHelper.getLastMessages()
|
this.lastLocationPoints = dbHelper.getLastMessages()
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SQLiteHelper(context: Context) :
|
private class SQLiteHelper(context: Context) :
|
||||||
|
@ -121,7 +141,7 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
internal fun getMessagesForUser(userId: Int, start: Long, end: Long): List<LocationMessage> {
|
internal fun getMessagesForUser(userId: Int, start: Long, end: Long): List<LocationMessage> {
|
||||||
val res = arrayListOf<LocationMessage>()
|
val res = arrayListOf<LocationMessage>()
|
||||||
readableDatabase?.rawQuery(
|
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 {
|
arrayOf(userId.toString()))?.apply {
|
||||||
if (moveToFirst()) {
|
if (moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
|
@ -133,6 +153,33 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
return res
|
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<Int, List<LocationMessage>> = mutableMapOf()
|
||||||
|
userLocations = UserLocations(userId, 0, emptyMap())
|
||||||
|
var userLocationsListBytetype: MutableList<LocationMessage>? = 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? {
|
internal fun getPreviousMessage(userId: Int, chatId: Long): LocationMessage? {
|
||||||
var res:LocationMessage? = null
|
var res:LocationMessage? = null
|
||||||
readableDatabase?.rawQuery(
|
readableDatabase?.rawQuery(
|
||||||
|
@ -149,7 +196,7 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
internal fun getIngoingMessages(currentUserId: Int, start: Long, end: Long): List<LocationMessage> {
|
internal fun getIngoingMessages(currentUserId: Int, start: Long, end: Long): List<LocationMessage> {
|
||||||
val res = arrayListOf<LocationMessage>()
|
val res = arrayListOf<LocationMessage>()
|
||||||
readableDatabase?.rawQuery(
|
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 {
|
arrayOf(currentUserId.toString()))?.apply {
|
||||||
if (moveToFirst()) {
|
if (moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
|
@ -161,10 +208,50 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun getIngoingUserLocations(currentUserId: Int, start: Long, end: Long): List<UserLocations> {
|
||||||
|
val res = arrayListOf<UserLocations>()
|
||||||
|
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<Int, List<LocationMessage>>? = null
|
||||||
|
var userLocationsListBytetype: MutableList<LocationMessage>? = 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<LocationMessage> {
|
internal fun getMessagesForUserInChat(userId: Int, chatId: Long, start: Long, end: Long): List<LocationMessage> {
|
||||||
val res = arrayListOf<LocationMessage>()
|
val res = arrayListOf<LocationMessage>()
|
||||||
readableDatabase?.rawQuery(
|
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 {
|
arrayOf(userId.toString(), chatId.toString()))?.apply {
|
||||||
if (moveToFirst()) {
|
if (moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
|
@ -189,12 +276,12 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun getLastMessages(): List<LocationMessage> {
|
internal fun getLastMessages(): MutableMap<LocationHistoryPoint, LatLon> {
|
||||||
val res = arrayListOf<LocationMessage>()
|
val res = mutableMapOf<LocationHistoryPoint, LatLon>()
|
||||||
readableDatabase?.rawQuery(TIMELINE_TABLE_SELECT, null)?.apply {
|
readableDatabase?.rawQuery("$TIMELINE_TABLE_SELECT_HISTORY_POINTS ORDER BY $COL_TIME ASC", null)?.apply {
|
||||||
if (moveToFirst()) {
|
if (moveToFirst()) {
|
||||||
do {
|
do {
|
||||||
res.add(readLocationMessage(this@apply))
|
// res.add(readLocationMessage(this@apply))
|
||||||
} while (moveToNext())
|
} while (moveToNext())
|
||||||
}
|
}
|
||||||
close()
|
close()
|
||||||
|
@ -233,6 +320,16 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
return BufferMessage(chatId, lat, lon, altitude, speed, hdop, bearing, date, type)
|
return BufferMessage(chatId, lat, lon, altitude, speed, hdop, bearing, date, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun readLocationHistoryPoint(cursor: Cursor): Pair<LocationHistoryPoint, LatLon> {
|
||||||
|
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() {
|
internal fun clearBufferedMessages() {
|
||||||
writableDatabase?.execSQL(BUFFER_TABLE_CLEAR)
|
writableDatabase?.execSQL(BUFFER_TABLE_CLEAR)
|
||||||
}
|
}
|
||||||
|
@ -288,6 +385,9 @@ class LocationMessages(val app: TelegramApplication) {
|
||||||
private const val TIMELINE_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_TIME, $COL_TYPE, $COL_MESSAGE_ID, $COL_DISTANCE_FROM_PREV 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_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_CLEAR = "DELETE FROM $TIMELINE_TABLE_NAME"
|
||||||
|
|
||||||
private const val TIMELINE_TABLE_DELETE = "DROP TABLE IF EXISTS $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 time: Long,
|
||||||
val type: Int)
|
val type: Int)
|
||||||
|
|
||||||
|
data class UserLocations(
|
||||||
|
var userId: Int,
|
||||||
|
var chatId: Long,
|
||||||
|
var locationsByType: Map<Int, List<LocationMessage>>
|
||||||
|
)
|
||||||
|
|
||||||
|
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 {
|
companion object {
|
||||||
|
|
||||||
const val TYPE_USER_MAP = 0
|
const val TYPE_USER_MAP = 0
|
||||||
|
|
|
@ -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 {
|
private fun bindService(packageName: String): Boolean {
|
||||||
return if (mIOsmAndAidlInterface == null) {
|
return if (mIOsmAndAidlInterface == null) {
|
||||||
val intent = Intent("net.osmand.aidl.OsmandAidlService")
|
val intent = Intent("net.osmand.aidl.OsmandAidlService")
|
||||||
|
|
|
@ -13,6 +13,8 @@ import org.json.JSONObject
|
||||||
|
|
||||||
private const val USER_SET_LIVE_PERIOD_DELAY_MS = 5000 // 5 sec
|
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) {
|
class ShareLocationHelper(private val app: TelegramApplication) {
|
||||||
|
|
||||||
private val log = PlatformUtil.getLog(ShareLocationHelper::class.java)
|
private val log = PlatformUtil.getLog(ShareLocationHelper::class.java)
|
||||||
|
@ -26,7 +28,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
||||||
var distance: Int = 0
|
var distance: Int = 0
|
||||||
private set
|
private set
|
||||||
|
|
||||||
var lastLocationMessageSentTime: Long = 0
|
var lastLocationUpdateTime: Long = 0
|
||||||
|
|
||||||
var lastLocation: Location? = null
|
var lastLocation: Location? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
|
@ -52,7 +54,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
||||||
if (app.settings.getChatsShareInfo().isNotEmpty()) {
|
if (app.settings.getChatsShareInfo().isNotEmpty()) {
|
||||||
shareLocationMessages(location, app.telegramHelper.getCurrentUserId())
|
shareLocationMessages(location, app.telegramHelper.getCurrentUserId())
|
||||||
}
|
}
|
||||||
lastLocationMessageSentTime = System.currentTimeMillis()
|
lastLocationUpdateTime = System.currentTimeMillis()
|
||||||
}
|
}
|
||||||
app.settings.updateSharingStatusHistory()
|
app.settings.updateSharingStatusHistory()
|
||||||
refreshNotification()
|
refreshNotification()
|
||||||
|
@ -188,6 +190,11 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
||||||
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 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 sharingMode = app.settings.currentSharingMode
|
||||||
val isBot = sharingMode != userId.toString()
|
val isBot = sharingMode != userId.toString()
|
||||||
var bufferedMessagesFull = false
|
var bufferedMessagesFull = false
|
||||||
|
@ -206,10 +213,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
||||||
if (shareInfo.pendingTdLib >= 10) {
|
if (shareInfo.pendingTdLib >= 10) {
|
||||||
bufferedMessagesFull = true
|
bufferedMessagesFull = true
|
||||||
}
|
}
|
||||||
val message = BufferMessage(
|
val message = BufferMessage(shareInfo.chatId, latitude, longitude, altitude, speed, accuracy, bearing, time, type)
|
||||||
shareInfo.chatId, latitude, longitude, location.altitude, location.speed.toDouble(),
|
|
||||||
location.accuracy.toDouble(), location.bearing.toDouble(), System.currentTimeMillis(), type
|
|
||||||
)
|
|
||||||
|
|
||||||
if (type == LocationMessages.TYPE_USER_MAP || type == LocationMessages.TYPE_BOT_MAP) {
|
if (type == LocationMessages.TYPE_USER_MAP || type == LocationMessages.TYPE_BOT_MAP) {
|
||||||
prepareMapMessage(shareInfo, message, isBot, sharingMode)
|
prepareMapMessage(shareInfo, message, isBot, sharingMode)
|
||||||
|
@ -219,6 +223,9 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
||||||
prepareMapAndTextMessage(shareInfo, message, isBot, sharingMode)
|
prepareMapAndTextMessage(shareInfo, message, isBot, sharingMode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (System.currentTimeMillis() - lastLocationUpdateTime > MY_LOCATION_UPDATE_MS) {
|
||||||
|
app.locationMessages.addMyLocationMessage(location)
|
||||||
|
}
|
||||||
if (bufferedMessagesFull) {
|
if (bufferedMessagesFull) {
|
||||||
checkNetworkType()
|
checkNetworkType()
|
||||||
}
|
}
|
||||||
|
@ -226,9 +233,9 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
||||||
|
|
||||||
private fun prepareTextMessage(shareInfo: TelegramSettings.ShareChatInfo,message: BufferMessage,isBot:Boolean, sharingMode: String) {
|
private fun prepareTextMessage(shareInfo: TelegramSettings.ShareChatInfo,message: BufferMessage,isBot:Boolean, sharingMode: String) {
|
||||||
log.debug("prepareTextMessage $message")
|
log.debug("prepareTextMessage $message")
|
||||||
shareInfo.collectedMessages++
|
|
||||||
if (shareInfo.currentTextMessageId == -1L) {
|
if (shareInfo.currentTextMessageId == -1L) {
|
||||||
if (shareInfo.pendingTextMessage) {
|
if (shareInfo.pendingTextMessage) {
|
||||||
|
shareInfo.collectedMessages++
|
||||||
app.locationMessages.addBufferedMessage(message)
|
app.locationMessages.addBufferedMessage(message)
|
||||||
} else {
|
} else {
|
||||||
if (isBot) {
|
if (isBot) {
|
||||||
|
@ -244,6 +251,7 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
||||||
if (shareInfo.pendingTdLib < 10) {
|
if (shareInfo.pendingTdLib < 10) {
|
||||||
app.telegramHelper.editTextLocation(shareInfo, message)
|
app.telegramHelper.editTextLocation(shareInfo, message)
|
||||||
} else {
|
} else {
|
||||||
|
shareInfo.collectedMessages++
|
||||||
app.locationMessages.addBufferedMessage(message)
|
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) {
|
private fun prepareMapMessage(shareInfo: TelegramSettings.ShareChatInfo,message: BufferMessage,isBot:Boolean, sharingMode: String) {
|
||||||
log.debug("prepareMapMessage $message")
|
log.debug("prepareMapMessage $message")
|
||||||
shareInfo.collectedMessages++
|
|
||||||
if (shareInfo.currentMapMessageId == -1L) {
|
if (shareInfo.currentMapMessageId == -1L) {
|
||||||
if (shareInfo.pendingMapMessage) {
|
if (shareInfo.pendingMapMessage) {
|
||||||
|
shareInfo.collectedMessages++
|
||||||
app.locationMessages.addBufferedMessage(message)
|
app.locationMessages.addBufferedMessage(message)
|
||||||
} else {
|
} else {
|
||||||
if (isBot) {
|
if (isBot) {
|
||||||
|
@ -279,8 +287,8 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
||||||
|
|
||||||
private fun prepareMapAndTextMessage(shareInfo: TelegramSettings.ShareChatInfo, message: BufferMessage, isBot:Boolean, sharingMode: String) {
|
private fun prepareMapAndTextMessage(shareInfo: TelegramSettings.ShareChatInfo, message: BufferMessage, isBot:Boolean, sharingMode: String) {
|
||||||
log.debug("prepareMapAndTextMessage $message")
|
log.debug("prepareMapAndTextMessage $message")
|
||||||
shareInfo.collectedMessages++
|
|
||||||
if (shareInfo.pendingMapMessage || shareInfo.pendingTextMessage || shareInfo.pendingTdLib >= 10) {
|
if (shareInfo.pendingMapMessage || shareInfo.pendingTextMessage || shareInfo.pendingTdLib >= 10) {
|
||||||
|
shareInfo.collectedMessages++
|
||||||
app.locationMessages.addBufferedMessage(message)
|
app.locationMessages.addBufferedMessage(message)
|
||||||
} else {
|
} else {
|
||||||
if (isBot) {
|
if (isBot) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
||||||
private var forcedStop: Boolean = false
|
private var forcedStop: Boolean = false
|
||||||
|
|
||||||
fun setupMapLayer() {
|
fun setupMapLayer() {
|
||||||
execOsmandApi {
|
osmandAidlHelper.execOsmandApi {
|
||||||
osmandAidlHelper.addMapLayer(MAP_LAYER_ID, "Telegram", 5.5f, null)
|
osmandAidlHelper.addMapLayer(MAP_LAYER_ID, "Telegram", 5.5f, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
||||||
if (item.latLon == null) {
|
if (item.latLon == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
execOsmandApi {
|
osmandAidlHelper.execOsmandApi {
|
||||||
osmandAidlHelper.showMapPoint(
|
osmandAidlHelper.showMapPoint(
|
||||||
MAP_LAYER_ID,
|
MAP_LAYER_ID,
|
||||||
item.getMapPointId(),
|
item.getMapPointId(),
|
||||||
|
@ -60,7 +60,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateLocationsOnMap() {
|
fun updateLocationsOnMap() {
|
||||||
execOsmandApi {
|
osmandAidlHelper.execOsmandApi {
|
||||||
val messages = telegramHelper.getMessages()
|
val messages = telegramHelper.getMessages()
|
||||||
for (message in messages) {
|
for (message in messages) {
|
||||||
val date = OsmandLocationUtils.getLastUpdatedTime(message)
|
val date = OsmandLocationUtils.getLastUpdatedTime(message)
|
||||||
|
@ -75,7 +75,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addOrUpdateLocationOnMap(message: TdApi.Message, update: Boolean = false) {
|
fun addOrUpdateLocationOnMap(message: TdApi.Message, update: Boolean = false) {
|
||||||
execOsmandApi {
|
osmandAidlHelper.execOsmandApi {
|
||||||
val chatId = message.chatId
|
val chatId = message.chatId
|
||||||
val chatTitle = telegramHelper.getChat(message.chatId)?.title
|
val chatTitle = telegramHelper.getChat(message.chatId)?.title
|
||||||
val content = message.content
|
val content = message.content
|
||||||
|
@ -133,7 +133,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showChatMessages(chatId: Long) {
|
fun showChatMessages(chatId: Long) {
|
||||||
execOsmandApi {
|
osmandAidlHelper.execOsmandApi {
|
||||||
val messages = telegramHelper.getChatMessages(chatId)
|
val messages = telegramHelper.getChatMessages(chatId)
|
||||||
for (message in messages) {
|
for (message in messages) {
|
||||||
addOrUpdateLocationOnMap(message)
|
addOrUpdateLocationOnMap(message)
|
||||||
|
@ -146,7 +146,7 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hideMessages(messages: List<TdApi.Message>) {
|
fun hideMessages(messages: List<TdApi.Message>) {
|
||||||
execOsmandApi {
|
osmandAidlHelper.execOsmandApi {
|
||||||
for (message in messages) {
|
for (message in messages) {
|
||||||
val user = telegramHelper.getUser(message.senderUserId)
|
val user = telegramHelper.getUser(message.senderUserId)
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
|
@ -257,13 +257,4 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
||||||
osmandAidlHelper.removeMapPoint(MAP_LAYER_ID, "${chatId}_${content.name}")
|
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -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 -> {
|
TdApi.UpdateMessageContent.CONSTRUCTOR -> {
|
||||||
val updateMessageContent = obj as TdApi.UpdateMessageContent
|
val updateMessageContent = obj as TdApi.UpdateMessageContent
|
||||||
val message = usersLocationMessages[updateMessageContent.messageId]
|
val message = usersLocationMessages[updateMessageContent.messageId]
|
||||||
|
@ -1325,9 +1343,12 @@ class TelegramHelper private constructor() {
|
||||||
val viaBot = isOsmAndBot(message.viaBotUserId)
|
val viaBot = isOsmAndBot(message.viaBotUserId)
|
||||||
message.content = if (newContent is TdApi.MessageText) {
|
message.content = if (newContent is TdApi.MessageText) {
|
||||||
parseTextLocation(newContent.text, (fromBot || viaBot))
|
parseTextLocation(newContent.text, (fromBot || viaBot))
|
||||||
} else if (newContent is TdApi.MessageLocation &&
|
} else if (newContent is TdApi.MessageLocation) {
|
||||||
(isOsmAndBot(message.senderUserId) || isOsmAndBot(message.viaBotUserId))) {
|
if(fromBot||viaBot){
|
||||||
parseOsmAndBotLocationContent(message.content as MessageOsmAndBotLocation, newContent)
|
parseOsmAndBotLocationContent(message.content as MessageOsmAndBotLocation, newContent)
|
||||||
|
} else {
|
||||||
|
OsmandLocationUtils.parseUserMapLocation(message)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
newContent
|
newContent
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
private fun botMessageToLocationItem(
|
||||||
chat: TdApi.Chat,
|
chat: TdApi.Chat,
|
||||||
content: MessageOsmAndBotLocation
|
content: MessageOsmAndBotLocation
|
||||||
|
@ -256,47 +252,31 @@ object TelegramUiHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun locationMessagesToChatItem(
|
fun userLocationsToChatItem(helper: TelegramHelper, userLocation: LocationMessages.UserLocations): LocationMessagesChatItem? {
|
||||||
helper: TelegramHelper,
|
val user = helper.getUser(userLocation.userId)
|
||||||
messages: List<LocationMessages.LocationMessage>
|
val chat = helper.getChat(userLocation.chatId)
|
||||||
): 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 {
|
return LocationMessagesChatItem().apply {
|
||||||
chatId = chat.id
|
if (chat != null) {
|
||||||
chatTitle = chat.title
|
chatId = chat.id
|
||||||
locationMessages = messages
|
chatTitle = chat.title
|
||||||
name = TelegramUiHelper.getUserName(user)
|
if (helper.isGroup(chat)) {
|
||||||
if (helper.isGroup(chat)) {
|
photoPath = helper.getUserPhotoPath(user)
|
||||||
photoPath = helper.getUserPhotoPath(user)
|
groupPhotoPath = chat.photo?.small?.local?.path
|
||||||
groupPhotoPath = chat.photo?.small?.local?.path
|
} else {
|
||||||
|
photoPath = user?.profilePhoto?.small?.local?.path
|
||||||
|
privateChat = helper.isPrivateChat(chat) || helper.isSecretChat(chat)
|
||||||
|
}
|
||||||
} else {
|
} 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)
|
grayscalePhotoPath = helper.getUserGreyPhotoPath(user)
|
||||||
placeholderId = R.drawable.img_user_picture
|
placeholderId = R.drawable.img_user_picture
|
||||||
userId = user.id
|
|
||||||
privateChat = helper.isPrivateChat(chat) || helper.isSecretChat(chat)
|
|
||||||
chatWithBot = helper.isBot(userId)
|
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() {
|
class LocationMessagesChatItem : ListItem() {
|
||||||
|
|
||||||
var locationMessages: List<LocationMessages.LocationMessage> = emptyList()
|
var userLocations: LocationMessages.UserLocations? = null
|
||||||
internal set
|
internal set
|
||||||
var groupPhotoPath: String? = null
|
var groupPhotoPath: String? = null
|
||||||
internal set
|
internal set
|
||||||
|
|
|
@ -19,8 +19,6 @@ 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.OsmandAidlHelper
|
import net.osmand.telegram.helpers.OsmandAidlHelper
|
||||||
import net.osmand.telegram.helpers.TelegramHelper
|
import net.osmand.telegram.helpers.TelegramHelper
|
||||||
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) {
|
if (app.telegramService == null) {
|
||||||
messages.forEach {
|
messages.forEach {
|
||||||
|
if (!it.isOutgoing) {
|
||||||
app.locationMessages.addNewLocationMessage(it)
|
app.locationMessages.addNewLocationMessage(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -718,8 +718,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
|
||||||
}
|
}
|
||||||
holder.gpsPointsCollected?.apply {
|
holder.gpsPointsCollected?.apply {
|
||||||
if (shareInfo != null) {
|
if (shareInfo != null) {
|
||||||
val bufferedMessages = shareInfo.pendingTdLib + app.locationMessages.getBufferedMessagesForChat(shareInfo.chatId).size
|
text = "${shareInfo.pendingTdLib + shareInfo.collectedMessages}"
|
||||||
text = "$bufferedMessages"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
holder.gpsPointsSent?.apply {
|
holder.gpsPointsSent?.apply {
|
||||||
|
|
|
@ -159,18 +159,18 @@ class TimelineTabFragment : Fragment() {
|
||||||
val res = mutableListOf<ListItem>()
|
val res = mutableListOf<ListItem>()
|
||||||
val currentUserId = telegramHelper.getCurrentUser()?.id
|
val currentUserId = telegramHelper.getCurrentUser()?.id
|
||||||
if (currentUserId != null) {
|
if (currentUserId != null) {
|
||||||
val outgoingMessages = app.locationMessages.getMessagesForUser(currentUserId, start, end)
|
val currentUserLocations = app.locationMessages.getUserLocations(currentUserId, start, end)
|
||||||
TelegramUiHelper.locationMessagesToChatItem(telegramHelper, outgoingMessages)?.also { chatItem ->
|
if (currentUserLocations != null) {
|
||||||
res.add(chatItem)
|
TelegramUiHelper.userLocationsToChatItem(telegramHelper, currentUserLocations)?.also { 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 ->
|
|
||||||
res.add(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)
|
adapter.items = sortAdapterItems(res)
|
||||||
|
@ -205,17 +205,21 @@ class TimelineTabFragment : Fragment() {
|
||||||
val lastItem = position == itemCount - 1
|
val lastItem = position == itemCount - 1
|
||||||
val item = items[position]
|
val item = items[position]
|
||||||
val currentUserId = telegramHelper.getCurrentUser()?.id ?: 0
|
val currentUserId = telegramHelper.getCurrentUser()?.id ?: 0
|
||||||
|
|
||||||
TelegramUiHelper.setupPhoto(app, holder.icon, item.photoPath, R.drawable.img_user_picture_active, false)
|
TelegramUiHelper.setupPhoto(app, holder.icon, item.photoPath, R.drawable.img_user_picture_active, false)
|
||||||
holder.title?.text = item.name
|
holder.title?.text = item.name
|
||||||
holder.bottomShadow?.visibility = if (lastItem) View.VISIBLE else View.GONE
|
holder.bottomShadow?.visibility = if (lastItem) View.VISIBLE else View.GONE
|
||||||
holder.lastTelegramUpdateTime?.visibility = View.GONE
|
holder.lastTelegramUpdateTime?.visibility = View.GONE
|
||||||
|
|
||||||
if (item is TelegramUiHelper.LocationMessagesChatItem) {
|
if (item is TelegramUiHelper.LocationMessagesChatItem ) {
|
||||||
val distance = OsmandFormatter.getFormattedDistance(getDistance(item.locationMessages),app)
|
val userLocations = item.userLocations
|
||||||
val name = if ((!item.privateChat || item.chatWithBot) && item.userId != currentUserId) item.getVisibleName() else ""
|
|
||||||
holder.groupDescrContainer?.visibility = View.VISIBLE
|
if(userLocations!=null){
|
||||||
holder.groupTitle?.text = "$distance (${getString(R.string.points_size, item.locationMessages.size)}) $name"
|
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)
|
TelegramUiHelper.setupPhoto(app, holder.groupImage, item.groupPhotoPath, item.placeholderId, false)
|
||||||
holder.userRow?.setOnClickListener {
|
holder.userRow?.setOnClickListener {
|
||||||
childFragmentManager.also {
|
childFragmentManager.also {
|
||||||
|
@ -229,12 +233,27 @@ class TimelineTabFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getDistance(messages: List<LocationMessages.LocationMessage>): Float {
|
private fun getDistanceAndCountedPoints(userLocations: LocationMessages.UserLocations): Pair<Float, Int> {
|
||||||
|
val textUserLoc = userLocations.locationsByType[LocationMessages.TYPE_USER_TEXT]
|
||||||
|
val textBotLoc = userLocations.locationsByType[LocationMessages.TYPE_BOT_TEXT]
|
||||||
var dist = 0.0
|
var dist = 0.0
|
||||||
messages.forEach {
|
var countedPoints = 0
|
||||||
dist += it.distanceFromPrev
|
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
|
override fun getItemCount() = items.size
|
||||||
|
|
|
@ -20,12 +20,10 @@ import android.widget.Toast
|
||||||
import net.osmand.PlatformUtil
|
import net.osmand.PlatformUtil
|
||||||
import net.osmand.aidl.gpx.AGpxBitmap
|
import net.osmand.aidl.gpx.AGpxBitmap
|
||||||
import net.osmand.telegram.R
|
import net.osmand.telegram.R
|
||||||
|
import net.osmand.telegram.helpers.LocationMessages
|
||||||
import net.osmand.telegram.helpers.OsmandAidlHelper
|
import net.osmand.telegram.helpers.OsmandAidlHelper
|
||||||
import net.osmand.telegram.helpers.TelegramUiHelper
|
import net.osmand.telegram.helpers.TelegramUiHelper
|
||||||
import net.osmand.telegram.utils.AndroidUtils
|
import net.osmand.telegram.utils.*
|
||||||
import net.osmand.telegram.utils.GPXUtilities
|
|
||||||
import net.osmand.telegram.utils.OsmandFormatter
|
|
||||||
import net.osmand.telegram.utils.OsmandLocationUtils
|
|
||||||
import net.osmand.util.Algorithms
|
import net.osmand.util.Algorithms
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
|
@ -52,6 +50,8 @@ class UserGpxInfoFragment : BaseDialogFragment() {
|
||||||
private var startCalendar = Calendar.getInstance()
|
private var startCalendar = Calendar.getInstance()
|
||||||
private var endCalendar = Calendar.getInstance()
|
private var endCalendar = Calendar.getInstance()
|
||||||
|
|
||||||
|
private var locationMessages = emptyList<LocationMessages.LocationMessage>()
|
||||||
|
|
||||||
private var userId = -1
|
private var userId = -1
|
||||||
private var chatId = -1L
|
private var chatId = -1L
|
||||||
|
|
||||||
|
@ -115,10 +115,10 @@ class UserGpxInfoFragment : BaseDialogFragment() {
|
||||||
setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_speed_average))
|
setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_speed_average))
|
||||||
}
|
}
|
||||||
mainView.findViewById<ImageView>(R.id.distance_icon).apply {
|
mainView.findViewById<ImageView>(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<ImageView>(R.id.duration_icon).apply {
|
mainView.findViewById<ImageView>(R.id.duration_icon).apply {
|
||||||
setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_altitude_range))
|
setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_time_span))
|
||||||
}
|
}
|
||||||
|
|
||||||
updateGPXStatisticRow()
|
updateGPXStatisticRow()
|
||||||
|
@ -192,7 +192,8 @@ class UserGpxInfoFragment : BaseDialogFragment() {
|
||||||
|
|
||||||
private fun saveCurrentGpxToFile(listener: OsmandLocationUtils.SaveGpxListener) {
|
private fun saveCurrentGpxToFile(listener: OsmandLocationUtils.SaveGpxListener) {
|
||||||
if (!gpxFile.isEmpty) {
|
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() {
|
private fun updateGpxInfo() {
|
||||||
val emm = app.locationMessages.getMessagesForUserInChat(
|
locationMessages = app.locationMessages.getMessagesForUserInChat(userId, chatId, startCalendar.timeInMillis, endCalendar.timeInMillis)
|
||||||
userId, chatId, startCalendar.timeInMillis, endCalendar.timeInMillis)
|
|
||||||
|
|
||||||
gpxFile = OsmandLocationUtils.convertLocationMessagesToGpxFiles(emm).firstOrNull()?:GPXUtilities.GPXFile()
|
gpxFile = OsmandLocationUtils.convertLocationMessagesToGpxFiles(locationMessages).firstOrNull()?:GPXUtilities.GPXFile()
|
||||||
updateGPXStatisticRow()
|
updateGPXStatisticRow()
|
||||||
updateDateAndTimeButtons()
|
updateDateAndTimeButtons()
|
||||||
updateGPXMap()
|
updateGPXMap()
|
||||||
|
@ -246,7 +246,9 @@ class UserGpxInfoFragment : BaseDialogFragment() {
|
||||||
val widthPixels = dm.widthPixels - (2 * app.resources.getDimensionPixelSize(R.dimen.content_padding_standard))
|
val widthPixels = dm.widthPixels - (2 * app.resources.getDimensionPixelSize(R.dimen.content_padding_standard))
|
||||||
val heightPixels = AndroidUtils.dpToPx(app, 152f)
|
val heightPixels = AndroidUtils.dpToPx(app, 152f)
|
||||||
val gpxUri = AndroidUtils.getUriForFile(app, File(path))
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package net.osmand.telegram.utils
|
||||||
|
|
||||||
import android.os.AsyncTask
|
import android.os.AsyncTask
|
||||||
import net.osmand.Location
|
import net.osmand.Location
|
||||||
|
import net.osmand.data.LatLon
|
||||||
import net.osmand.telegram.TelegramApplication
|
import net.osmand.telegram.TelegramApplication
|
||||||
import net.osmand.telegram.helpers.LocationMessages
|
import net.osmand.telegram.helpers.LocationMessages
|
||||||
import net.osmand.telegram.helpers.LocationMessages.BufferMessage
|
import net.osmand.telegram.helpers.LocationMessages.BufferMessage
|
||||||
|
@ -15,6 +16,7 @@ import java.io.File
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
const val TRACKS_DIR = "tracker/"
|
||||||
|
|
||||||
object OsmandLocationUtils {
|
object OsmandLocationUtils {
|
||||||
|
|
||||||
|
@ -83,10 +85,11 @@ object OsmandLocationUtils {
|
||||||
lat = messageLocation.location.latitude
|
lat = messageLocation.location.latitude
|
||||||
lon = messageLocation.location.longitude
|
lon = messageLocation.location.longitude
|
||||||
lastUpdated = getLastUpdatedTime(message)
|
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
|
var locationMessage: LocationMessage? = null
|
||||||
val oldContent = message.content
|
val oldContent = message.content
|
||||||
val messageType = getMessageType(message,helper)
|
val messageType = getMessageType(message,helper)
|
||||||
|
@ -114,10 +117,8 @@ object OsmandLocationUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsedMessageContent != null) {
|
if (parsedMessageContent != null) {
|
||||||
val distanceFromPrev = if (previousMessage != null) {
|
val distanceFromPrev = if (previousMessageLatLon != null) {
|
||||||
MapUtils.getDistance(previousMessage.lat, previousMessage.lon,
|
MapUtils.getDistance(previousMessageLatLon, parsedMessageContent.lat, parsedMessageContent.lon) } else 0.0
|
||||||
parsedMessageContent.lat, parsedMessageContent.lon)
|
|
||||||
} else 0.0
|
|
||||||
|
|
||||||
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,
|
||||||
|
@ -403,11 +404,16 @@ object OsmandLocationUtils {
|
||||||
var segment: GPXUtilities.TrkSegment? = null
|
var segment: GPXUtilities.TrkSegment? = null
|
||||||
var track: GPXUtilities.Track? = null
|
var track: GPXUtilities.Track? = null
|
||||||
var gpx: GPXUtilities.GPXFile? = null
|
var gpx: GPXUtilities.GPXFile? = null
|
||||||
|
var countedLocations = 0
|
||||||
|
|
||||||
items.forEach {
|
items.forEach {
|
||||||
val userId = it.userId
|
val userId = it.userId
|
||||||
val chatId = it.chatId
|
val chatId = it.chatId
|
||||||
val time = it.time
|
val time = it.time
|
||||||
|
if (previousTime >= time) {
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
countedLocations++
|
||||||
if (previousUserId != userId || (newGpxPerChat && previousChatId != chatId)) {
|
if (previousUserId != userId || (newGpxPerChat && previousChatId != chatId)) {
|
||||||
gpx = GPXUtilities.GPXFile()
|
gpx = GPXUtilities.GPXFile()
|
||||||
gpx!!.chatId = chatId
|
gpx!!.chatId = chatId
|
||||||
|
@ -521,10 +527,6 @@ object OsmandLocationUtils {
|
||||||
userId.toString() + "_" + SimpleDateFormat("yyyy-MM-dd_HH-mm_EEE", Locale.US).format(Date(pt.time))
|
userId.toString() + "_" + SimpleDateFormat("yyyy-MM-dd_HH-mm_EEE", Locale.US).format(Date(pt.time))
|
||||||
}
|
}
|
||||||
fout = File(dir, "$fileName.gpx")
|
fout = File(dir, "$fileName.gpx")
|
||||||
var ind = 1
|
|
||||||
while (fout.exists()) {
|
|
||||||
fout = File(dir, "${fileName}_${++ind}.gpx")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
val warn = GPXUtilities.writeGpxFile(fout, gpxFile, app)
|
val warn = GPXUtilities.writeGpxFile(fout, gpxFile, app)
|
||||||
if (warn != null) {
|
if (warn != null) {
|
||||||
|
|
Loading…
Reference in a new issue