Merge pull request #7297 from osmandapp/TrackerLiveTrack
Tracker live track colors
This commit is contained in:
commit
39d8ae0ca2
8 changed files with 105 additions and 42 deletions
|
@ -11,13 +11,15 @@ public class AGpxFile implements Parcelable {
|
|||
private long modifiedTime;
|
||||
private long fileSize;
|
||||
private boolean active;
|
||||
private String color;
|
||||
private AGpxFileDetails details;
|
||||
|
||||
public AGpxFile(@NonNull String fileName, long modifiedTime, long fileSize, boolean active, @Nullable AGpxFileDetails details) {
|
||||
public AGpxFile(@NonNull String fileName, long modifiedTime, long fileSize, boolean active, String color, @Nullable AGpxFileDetails details) {
|
||||
this.fileName = fileName;
|
||||
this.modifiedTime = modifiedTime;
|
||||
this.fileSize = fileSize;
|
||||
this.active = active;
|
||||
this.color = color;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
|
@ -52,6 +54,10 @@ public class AGpxFile implements Parcelable {
|
|||
return active;
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public AGpxFileDetails getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
@ -66,6 +72,7 @@ public class AGpxFile implements Parcelable {
|
|||
if (details != null) {
|
||||
out.writeParcelable(details, flags);
|
||||
}
|
||||
out.writeString(color);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
|
@ -74,16 +81,16 @@ public class AGpxFile implements Parcelable {
|
|||
fileSize = in.readLong();
|
||||
active = in.readByte() != 0;
|
||||
|
||||
boolean hasDetails= in.readByte() != 0;
|
||||
boolean hasDetails = in.readByte() != 0;
|
||||
if (hasDetails) {
|
||||
details = in.readParcelable(AGpxFileDetails.class.getClassLoader());
|
||||
} else {
|
||||
details = null;
|
||||
}
|
||||
color = in.readString();
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,7 @@ import android.text.SpannableStringBuilder
|
|||
import android.text.style.ForegroundColorSpan
|
||||
import net.osmand.PlatformUtil
|
||||
import net.osmand.telegram.helpers.OsmandAidlHelper
|
||||
import net.osmand.telegram.helpers.ShowLocationHelper
|
||||
import net.osmand.telegram.helpers.TelegramHelper
|
||||
import net.osmand.telegram.utils.AndroidUtils
|
||||
import net.osmand.telegram.utils.OsmandApiUtils
|
||||
|
@ -112,7 +113,7 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
private var shareChatsInfo = ConcurrentHashMap<Long, ShareChatInfo>()
|
||||
private var hiddenOnMapChats: Set<Long> = emptySet()
|
||||
private var shareDevices: Set<DeviceBot> = emptySet()
|
||||
private var liveTracksInfo: Set<LiveTrackInfo> = emptySet()
|
||||
private var liveTracksInfo = emptyList<LiveTrackInfo>()
|
||||
|
||||
var sharingStatusChanges = ConcurrentLinkedQueue<SharingStatus>()
|
||||
|
||||
|
@ -177,6 +178,9 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
|
||||
fun getLiveTracksInfo() = liveTracksInfo
|
||||
|
||||
fun getLiveTrackInfo(userId: Int, chatId: Long, deviceName: String) =
|
||||
liveTracksInfo.firstOrNull { it.userId == userId && it.chatId == chatId && it.deviceName == deviceName }
|
||||
|
||||
fun isShowingChatOnMap(chatId: Long) = !hiddenOnMapChats.contains(chatId)
|
||||
|
||||
fun isLiveTrackEnabled(userId: Int, chatId: Long, deviceName: String) =
|
||||
|
@ -185,11 +189,12 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
fun updateLiveTrack(userId: Int, chatId: Long, deviceName: String, enable: Boolean) {
|
||||
val tracksInfo = liveTracksInfo.toMutableList()
|
||||
if (enable) {
|
||||
tracksInfo.add(LiveTrackInfo(userId, chatId, deviceName))
|
||||
val colorIndex = if (tracksInfo.size > 0) (tracksInfo.last().colorIndex + 1) % ShowLocationHelper.GPX_COLORS_COUNT else 0
|
||||
tracksInfo.add(LiveTrackInfo(userId, chatId, deviceName, colorIndex))
|
||||
} else {
|
||||
tracksInfo.remove(LiveTrackInfo(userId, chatId, deviceName))
|
||||
tracksInfo.removeAll { it.userId == userId && it.chatId == chatId && it.deviceName == deviceName }
|
||||
}
|
||||
liveTracksInfo = tracksInfo.toHashSet()
|
||||
liveTracksInfo = tracksInfo.toList()
|
||||
}
|
||||
|
||||
fun removeNonexistingChats(presentChatIds: List<Long>) {
|
||||
|
@ -747,6 +752,7 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
obj.put(LiveTrackInfo.USER_ID, liveTrackInfo.userId)
|
||||
obj.put(LiveTrackInfo.CHAT_ID, liveTrackInfo.chatId)
|
||||
obj.put(LiveTrackInfo.DEVICE_NAME, liveTrackInfo.deviceName)
|
||||
obj.put(LiveTrackInfo.COLOR_INDEX, liveTrackInfo.colorIndex)
|
||||
put(obj)
|
||||
}
|
||||
}
|
||||
|
@ -863,10 +869,11 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
val userId = obj.optInt(LiveTrackInfo.USER_ID)
|
||||
val chatId = obj.optLong(LiveTrackInfo.CHAT_ID)
|
||||
val deviceName = obj.optString(LiveTrackInfo.DEVICE_NAME)
|
||||
val colorIndex = obj.optInt(LiveTrackInfo.COLOR_INDEX)
|
||||
|
||||
list.add(LiveTrackInfo(userId, chatId, deviceName))
|
||||
list.add(LiveTrackInfo(userId, chatId, deviceName, colorIndex))
|
||||
}
|
||||
liveTracksInfo = list.toHashSet()
|
||||
liveTracksInfo = list.toList()
|
||||
}
|
||||
|
||||
private fun parseShareDevices(json: String) {
|
||||
|
@ -1192,12 +1199,13 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
}
|
||||
}
|
||||
|
||||
data class LiveTrackInfo(val userId: Int, val chatId: Long, val deviceName: String) {
|
||||
data class LiveTrackInfo(val userId: Int, val chatId: Long, val deviceName: String, val colorIndex: Int) {
|
||||
companion object {
|
||||
|
||||
internal const val USER_ID = "userId"
|
||||
internal const val CHAT_ID = "chatId"
|
||||
internal const val DEVICE_NAME = "deviceName"
|
||||
internal const val COLOR_INDEX = "colorIndex"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import net.osmand.telegram.TelegramApplication
|
|||
import net.osmand.telegram.utils.OsmandLocationUtils
|
||||
import net.osmand.util.MapUtils
|
||||
import org.drinkless.td.libcore.telegram.TdApi
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
|
||||
class LocationMessages(val app: TelegramApplication) {
|
||||
|
||||
|
@ -18,7 +19,7 @@ class LocationMessages(val app: TelegramApplication) {
|
|||
|
||||
private var bufferedMessages = emptyList<BufferMessage>()
|
||||
|
||||
private var lastLocationPoints = mutableListOf<LocationMessage>()
|
||||
private var lastLocationPoints = ConcurrentLinkedQueue<LocationMessage>()
|
||||
|
||||
private val dbHelper: SQLiteHelper
|
||||
|
||||
|
@ -69,7 +70,7 @@ class LocationMessages(val app: TelegramApplication) {
|
|||
}
|
||||
|
||||
fun getMessagesForUserInChat(userId: Int, chatId: Long, deviceName: String, start: Long, end: Long): List<LocationMessage> {
|
||||
return dbHelper.getMessagesForUserInChat(userId, chatId,deviceName, start, end)
|
||||
return dbHelper.getMessagesForUserInChat(userId, chatId, deviceName, start, end)
|
||||
}
|
||||
|
||||
fun getMessagesForUser(userId: Int, start: Long, end: Long): List<LocationMessage> {
|
||||
|
@ -144,7 +145,7 @@ class LocationMessages(val app: TelegramApplication) {
|
|||
}
|
||||
|
||||
private fun readLastMessages() {
|
||||
this.lastLocationPoints = dbHelper.getLastMessages()
|
||||
this.lastLocationPoints.addAll(dbHelper.getLastMessages())
|
||||
}
|
||||
|
||||
private class SQLiteHelper(context: Context) :
|
||||
|
|
|
@ -39,6 +39,14 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
const val DIRECTION_ICON_ID = "ic_action_start_navigation"
|
||||
|
||||
const val LIVE_TRACKS_DIR = "livetracks"
|
||||
|
||||
const val GPX_COLORS_COUNT = 10
|
||||
|
||||
val GPX_COLORS = arrayOf(
|
||||
"red", "orange", "lightblue", "blue", "purple",
|
||||
"translucent_red", "translucent_orange", "translucent_lightblue",
|
||||
"translucent_blue", "translucent_purple"
|
||||
)
|
||||
}
|
||||
|
||||
private val telegramHelper = app.telegramHelper
|
||||
|
@ -264,14 +272,15 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
|
||||
val importedGpxFiles = osmandAidlHelper.importedGpxFiles
|
||||
gpxFiles.forEach {
|
||||
if (!isGpxAlreadyImported(importedGpxFiles, it)) {
|
||||
if (!checkAlreadyImportedGpx(importedGpxFiles, it)) {
|
||||
val listener = object : OsmandLocationUtils.SaveGpxListener {
|
||||
|
||||
override fun onSavingGpxFinish(path: String) {
|
||||
log.debug("LiveTracks onSavingGpxFinish $path time ${startTime - System.currentTimeMillis()}")
|
||||
val uri = AndroidUtils.getUriForFile(app, File(path))
|
||||
val destinationPath = "$LIVE_TRACKS_DIR/${it.metadata.name}.gpx"
|
||||
osmandAidlHelper.importGpxFromUri(uri, destinationPath, GPXUtilities.GPXColor.AQUA.name, true)
|
||||
val color = it.extensionsToRead["color"] ?: ""
|
||||
osmandAidlHelper.importGpxFromUri(uri, destinationPath, color, true)
|
||||
log.debug("LiveTracks importGpxFromUri finish time ${startTime - System.currentTimeMillis()}")
|
||||
}
|
||||
|
||||
|
@ -285,12 +294,16 @@ class ShowLocationHelper(private val app: TelegramApplication) {
|
|||
}
|
||||
}
|
||||
|
||||
private fun isGpxAlreadyImported(importedGpxFiles: List<AGpxFile>?, gpxFile: GPXUtilities.GPXFile): Boolean {
|
||||
private fun checkAlreadyImportedGpx(importedGpxFiles: List<AGpxFile>?, gpxFile: GPXUtilities.GPXFile): Boolean {
|
||||
if (importedGpxFiles != null && importedGpxFiles.isNotEmpty()) {
|
||||
val name = "${gpxFile.metadata.name}.gpx"
|
||||
val aGpxFile = importedGpxFiles.firstOrNull { it.fileName == name }
|
||||
|
||||
if (aGpxFile != null) {
|
||||
val color = aGpxFile.color
|
||||
if (!color.isNullOrEmpty()) {
|
||||
gpxFile.extensionsToWrite["color"] = color
|
||||
}
|
||||
val startTimeImported = aGpxFile.details?.startTime
|
||||
val endTimeImported = aGpxFile.details?.endTime
|
||||
if (startTimeImported != null && endTimeImported != null) {
|
||||
|
|
|
@ -8,6 +8,7 @@ import net.osmand.telegram.TelegramApplication
|
|||
import net.osmand.telegram.helpers.LocationMessages
|
||||
import net.osmand.telegram.helpers.LocationMessages.BufferMessage
|
||||
import net.osmand.telegram.helpers.LocationMessages.LocationMessage
|
||||
import net.osmand.telegram.helpers.ShowLocationHelper
|
||||
import net.osmand.telegram.helpers.TelegramHelper
|
||||
import net.osmand.telegram.helpers.TelegramUiHelper
|
||||
import net.osmand.util.GeoPointParserUtil
|
||||
|
@ -420,6 +421,7 @@ object OsmandLocationUtils {
|
|||
var previousTime: Long = -1
|
||||
var previousChatId: Long = -1
|
||||
var previousUserId = -1
|
||||
var previousDeviceName = ""
|
||||
var segment: GPXUtilities.TrkSegment? = null
|
||||
var track: GPXUtilities.Track? = null
|
||||
var gpx: GPXUtilities.GPXFile? = null
|
||||
|
@ -428,15 +430,16 @@ object OsmandLocationUtils {
|
|||
items.forEach {
|
||||
val userId = it.userId
|
||||
val chatId = it.chatId
|
||||
val deviceName = it.deviceName
|
||||
val time = it.time
|
||||
if (previousTime >= time) {
|
||||
return@forEach
|
||||
}
|
||||
countedLocations++
|
||||
if (previousUserId != userId || (newGpxPerChat && previousChatId != chatId)) {
|
||||
if (previousUserId != userId || previousDeviceName != deviceName || (newGpxPerChat && previousChatId != chatId)) {
|
||||
gpx = GPXUtilities.GPXFile(app.packageName).apply {
|
||||
metadata = GPXUtilities.Metadata().apply {
|
||||
name = getGpxFileNameForUserId(app, userId, time)
|
||||
name = getGpxFileNameForUserId(app, userId, chatId, time)
|
||||
}
|
||||
val colorIndex = app.settings.getLiveTrackInfo(userId, chatId, deviceName)?.colorIndex ?: -1
|
||||
if (colorIndex != -1) {
|
||||
extensionsToWrite["color"] = ShowLocationHelper.GPX_COLORS[colorIndex]
|
||||
}
|
||||
}
|
||||
previousTime = 0
|
||||
|
@ -444,6 +447,10 @@ object OsmandLocationUtils {
|
|||
segment = null
|
||||
dataTracks.add(gpx!!)
|
||||
}
|
||||
if (previousTime >= time) {
|
||||
return@forEach
|
||||
}
|
||||
countedLocations++
|
||||
val pt = GPXUtilities.WptPt()
|
||||
pt.lat = it.lat
|
||||
pt.lon = it.lon
|
||||
|
@ -472,6 +479,7 @@ object OsmandLocationUtils {
|
|||
previousTime = time
|
||||
previousUserId = userId
|
||||
previousChatId = chatId
|
||||
previousDeviceName = deviceName
|
||||
}
|
||||
|
||||
return dataTracks
|
||||
|
@ -485,15 +493,15 @@ object OsmandLocationUtils {
|
|||
}
|
||||
}
|
||||
|
||||
fun getGpxFileNameForUserId(app: TelegramApplication, userId: Int, time: Long): String {
|
||||
fun getGpxFileNameForUserId(app: TelegramApplication, userId: Int, chatId: Long, time: Long): String {
|
||||
var userName = userId.toString()
|
||||
try {
|
||||
val user = app.telegramHelper.getUser(userId)
|
||||
if (user != null) {
|
||||
userName = TelegramUiHelper.getUserName(user)
|
||||
}
|
||||
} catch (e: NumberFormatException) {
|
||||
//ignore
|
||||
val user = app.telegramHelper.getUser(userId)
|
||||
if (user != null) {
|
||||
userName = TelegramUiHelper.getUserName(user)
|
||||
}
|
||||
val chat = app.telegramHelper.getChat(chatId)
|
||||
if (chat != null && app.telegramHelper.isGroup(chat)) {
|
||||
return "${userName}_${chat.title}_${UTC_DATE_FORMAT.format(Date(time))}"
|
||||
}
|
||||
return "${userName}_${UTC_DATE_FORMAT.format(Date(time))}"
|
||||
}
|
||||
|
|
|
@ -1477,12 +1477,17 @@ public class OsmandAidlApi {
|
|||
boolean active = app.getSelectedGpxHelper().getSelectedFileByPath(file.getAbsolutePath()) != null;
|
||||
long modifiedTime = dataItem.getFileLastModifiedTime();
|
||||
long fileSize = file.length();
|
||||
int color = dataItem.getColor();
|
||||
String colorName = "";
|
||||
if (color != 0) {
|
||||
colorName = ConfigureMapMenu.GpxAppearanceAdapter.parseTrackColorName(app.getRendererRegistry().getCurrentSelectedRenderer(), color);
|
||||
}
|
||||
AGpxFileDetails details = null;
|
||||
GPXTrackAnalysis analysis = dataItem.getAnalysis();
|
||||
if (analysis != null) {
|
||||
details = createGpxFileDetails(analysis);
|
||||
}
|
||||
files.add(new AGpxFile(fileName, modifiedTime, fileSize, active, details));
|
||||
files.add(new AGpxFile(fileName, modifiedTime, fileSize, active, colorName, details));
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,6 @@ import android.os.Parcel;
|
|||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class AGpxFile implements Parcelable {
|
||||
|
||||
|
@ -14,13 +11,15 @@ public class AGpxFile implements Parcelable {
|
|||
private long modifiedTime;
|
||||
private long fileSize;
|
||||
private boolean active;
|
||||
private String color;
|
||||
private AGpxFileDetails details;
|
||||
|
||||
public AGpxFile(@NonNull String fileName, long modifiedTime, long fileSize, boolean active, @Nullable AGpxFileDetails details) {
|
||||
public AGpxFile(@NonNull String fileName, long modifiedTime, long fileSize, boolean active, String color, @Nullable AGpxFileDetails details) {
|
||||
this.fileName = fileName;
|
||||
this.modifiedTime = modifiedTime;
|
||||
this.fileSize = fileSize;
|
||||
this.active = active;
|
||||
this.color = color;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
|
@ -55,6 +54,10 @@ public class AGpxFile implements Parcelable {
|
|||
return active;
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public AGpxFileDetails getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
@ -69,6 +72,7 @@ public class AGpxFile implements Parcelable {
|
|||
if (details != null) {
|
||||
out.writeParcelable(details, flags);
|
||||
}
|
||||
out.writeString(color);
|
||||
}
|
||||
|
||||
private void readFromParcel(Parcel in) {
|
||||
|
@ -77,16 +81,16 @@ public class AGpxFile implements Parcelable {
|
|||
fileSize = in.readLong();
|
||||
active = in.readByte() != 0;
|
||||
|
||||
boolean hasDetails= in.readByte() != 0;
|
||||
boolean hasDetails = in.readByte() != 0;
|
||||
if (hasDetails) {
|
||||
details = in.readParcelable(AGpxFileDetails.class.getClassLoader());
|
||||
} else {
|
||||
details = null;
|
||||
}
|
||||
color = in.readString();
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -23,7 +23,6 @@ import android.widget.ListView;
|
|||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.io.File;
|
||||
import net.osmand.AndroidUtils;
|
||||
import net.osmand.GPXUtilities;
|
||||
import net.osmand.PlatformUtil;
|
||||
|
@ -58,6 +57,7 @@ import net.osmand.util.Algorithms;
|
|||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -1415,11 +1415,11 @@ public class ConfigureMapMenu {
|
|||
public static int parseTrackColor(RenderingRulesStorage renderer, String colorName) {
|
||||
int defaultColor = -1;
|
||||
RenderingRule gpxRule = null;
|
||||
if(renderer!=null) {
|
||||
if (renderer != null) {
|
||||
gpxRule = renderer.getRenderingAttributeRule("gpx");
|
||||
}
|
||||
if (gpxRule != null && gpxRule.getIfElseChildren().size() > 0) {
|
||||
List<RenderingRule> rules = renderer.getRenderingAttributeRule("gpx").getIfElseChildren().get(0).getIfElseChildren();
|
||||
List<RenderingRule> rules = gpxRule.getIfElseChildren().get(0).getIfElseChildren();
|
||||
for (RenderingRule r : rules) {
|
||||
String cName = r.getStringPropertyValue(CURRENT_TRACK_COLOR_ATTR);
|
||||
if (!Algorithms.isEmpty(cName) && cName.equals(colorName)) {
|
||||
|
@ -1433,6 +1433,23 @@ public class ConfigureMapMenu {
|
|||
return defaultColor;
|
||||
}
|
||||
|
||||
public static String parseTrackColorName(RenderingRulesStorage renderer, int color) {
|
||||
RenderingRule gpxRule = null;
|
||||
if (renderer != null) {
|
||||
gpxRule = renderer.getRenderingAttributeRule("gpx");
|
||||
}
|
||||
if (gpxRule != null && gpxRule.getIfElseChildren().size() > 0) {
|
||||
List<RenderingRule> rules = gpxRule.getIfElseChildren().get(0).getIfElseChildren();
|
||||
for (RenderingRule r : rules) {
|
||||
String cName = r.getStringPropertyValue(CURRENT_TRACK_COLOR_ATTR);
|
||||
if (!Algorithms.isEmpty(cName) && color == r.getIntPropertyValue(COLOR_ATTR)) {
|
||||
return cName;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Algorithms.colorToString(color);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
|
||||
|
|
Loading…
Reference in a new issue