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