diff --git a/OsmAnd-telegram/res/layout/fragment_user_gpx_info.xml b/OsmAnd-telegram/res/layout/fragment_user_gpx_info.xml index 4d7636dc1b..205496fddf 100644 --- a/OsmAnd-telegram/res/layout/fragment_user_gpx_info.xml +++ b/OsmAnd-telegram/res/layout/fragment_user_gpx_info.xml @@ -188,6 +188,24 @@ + + #5959FF + #F54522 + diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt index fe0c5f2bf1..c90caecd77 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt @@ -27,6 +27,8 @@ val ADDITIONAL_ACTIVE_TIME_VALUES_SEC = listOf(15 * 60L, 30 * 60L, 60 * 60L, 180 const val SHARE_DEVICES_KEY = "devices" +const val LIVE_TRACKS_KEY = "live_tracks" + private val SEND_MY_LOC_VALUES_SEC = listOf(1L, 2L, 3L, 5L, 10L, 15L, 30L, 60L, 90L, 2 * 60L, 3 * 60L, 5 * 60L) private val STALE_LOC_VALUES_SEC = @@ -110,6 +112,7 @@ class TelegramSettings(private val app: TelegramApplication) { private var shareChatsInfo = ConcurrentHashMap() private var hiddenOnMapChats: Set = emptySet() private var shareDevices: Set = emptySet() + private var liveTracksInfo: Set = emptySet() var sharingStatusChanges = ConcurrentLinkedQueue() @@ -163,6 +166,19 @@ class TelegramSettings(private val app: TelegramApplication) { fun isShowingChatOnMap(chatId: Long) = !hiddenOnMapChats.contains(chatId) + fun isLiveTrackEnabled(userId: Int, chatId: Long, deviceName: String) = + liveTracksInfo.any { (it.chatId == chatId && it.userId == userId && it.deviceName == deviceName) } + + fun updateLiveTrack(userId: Int, chatId: Long, deviceName: String, enable: Boolean) { + val tracksInfo = liveTracksInfo.toMutableList() + if (enable) { + tracksInfo.add(LiveTrackInfo(userId, chatId, deviceName)) + } else { + tracksInfo.remove(LiveTrackInfo(userId, chatId, deviceName)) + } + liveTracksInfo = tracksInfo.toHashSet() + } + fun removeNonexistingChats(presentChatIds: List) { val hiddenChats = hiddenOnMapChats.toMutableList() hiddenChats.intersect(presentChatIds) @@ -610,6 +626,11 @@ class TelegramSettings(private val app: TelegramApplication) { edit.putString(PROXY_PREFERENCES_KEY, jsonObjectProxy.toString()) } + val jsonArrayLiveTracks = convertLiveTracksInfoToJson() + if (jsonArrayLiveTracks != null) { + edit.putString(LIVE_TRACKS_KEY, jsonArrayLiveTracks.toString()) + } + edit.apply() } @@ -674,7 +695,13 @@ class TelegramSettings(private val app: TelegramApplication) { try { parseProxyPreferences(JSONObject(prefs.getString(PROXY_PREFERENCES_KEY, ""))) } catch (e: JSONException) { - e.printStackTrace() + log.error(e) + } + + try { + parseLiveTracks(JSONArray(prefs.getString(LIVE_TRACKS_KEY, ""))) + } catch (e: JSONException) { + log.error(e) } } @@ -699,6 +726,23 @@ class TelegramSettings(private val app: TelegramApplication) { } } + private fun convertLiveTracksInfoToJson(): JSONArray? { + return try { + JSONArray().apply { + liveTracksInfo.forEach { liveTrackInfo -> + val obj = JSONObject() + obj.put(LiveTrackInfo.USER_ID, liveTrackInfo.userId) + obj.put(LiveTrackInfo.CHAT_ID, liveTrackInfo.chatId) + obj.put(LiveTrackInfo.DEVICE_NAME, liveTrackInfo.deviceName) + put(obj) + } + } + } catch (e: JSONException) { + log.error(e) + null + } + } + private fun convertProxyPrefToJson(): JSONObject? { return try { val proxyPref = currentProxyPref @@ -746,7 +790,7 @@ class TelegramSettings(private val app: TelegramApplication) { } jArray } catch (e: JSONException) { - e.printStackTrace() + log.error(e) null } } @@ -799,6 +843,19 @@ class TelegramSettings(private val app: TelegramApplication) { } } + private fun parseLiveTracks(json: JSONArray) { + val list = mutableListOf() + for (i in 0 until json.length()) { + val obj = json.getJSONObject(i) + val userId = obj.optInt(LiveTrackInfo.USER_ID) + val chatId = obj.optLong(LiveTrackInfo.CHAT_ID) + val deviceName = obj.optString(LiveTrackInfo.DEVICE_NAME) + + list.add(LiveTrackInfo(userId, chatId, deviceName)) + } + liveTracksInfo = list.toHashSet() + } + private fun parseShareDevices(json: String) { shareDevices = OsmandApiUtils.parseJsonContents(json).toHashSet() } @@ -1122,6 +1179,15 @@ class TelegramSettings(private val app: TelegramApplication) { } } + data class LiveTrackInfo(val userId: Int, val chatId: Long, val deviceName: String) { + companion object { + + internal const val USER_ID = "userId" + internal const val CHAT_ID = "chatId" + internal const val DEVICE_NAME = "deviceName" + } + } + enum class ProxyType { MTPROTO, SOCKS5 } diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/UserGpxInfoFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/UserGpxInfoFragment.kt index a2b689cf0d..722c90b35e 100644 --- a/OsmAnd-telegram/src/net/osmand/telegram/ui/UserGpxInfoFragment.kt +++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/UserGpxInfoFragment.kt @@ -7,6 +7,7 @@ import android.content.Intent import android.content.pm.PackageManager import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.Drawable +import android.graphics.drawable.LayerDrawable import android.os.Build import android.os.Bundle import android.support.design.widget.Snackbar @@ -46,6 +47,7 @@ class UserGpxInfoFragment : BaseDialogFragment() { private lateinit var timeStartBtn: TextView private lateinit var dateEndBtn: TextView private lateinit var timeEndBtn: TextView + private lateinit var liveBtn: TextView private lateinit var avgElevationTv: TextView private lateinit var avgSpeedTv: TextView @@ -122,6 +124,15 @@ class UserGpxInfoFragment : BaseDialogFragment() { dateEndBtn = mainView.findViewById(R.id.date_end_btn) timeEndBtn = mainView.findViewById(R.id.time_end_btn) + liveBtn = mainView.findViewById(R.id.live_btn).apply { + setOnClickListener { + val enabled = settings.isLiveTrackEnabled(userId, chatId, deviceName) + settings.updateLiveTrack(userId, chatId, deviceName, !enabled) + updateLiveTrackBtn() + } + } + updateLiveTrackBtn() + dateStartBtn.setOnClickListener { selectStartDate() } timeStartBtn.setOnClickListener { selectStartTime() } dateEndBtn.setOnClickListener { selectEndDate() } @@ -241,6 +252,15 @@ class UserGpxInfoFragment : BaseDialogFragment() { textView.setTextColor(AndroidUtils.createPressedColorStateList(app, true, R.color.ctrl_active_light, R.color.ctrl_light)) } + private fun updateLiveTrackBtn() { + val enabled = settings.isLiveTrackEnabled(userId, chatId, deviceName) + val icon = getLiveTrackBtnIcon(enabled) + val normalTextColor = if (enabled) R.color.ctrl_active_light else R.color.secondary_text_light + + liveBtn.setTextColor(AndroidUtils.createPressedColorStateList(app, true, normalTextColor, R.color.ctrl_light)) + liveBtn.setCompoundDrawablesWithIntrinsicBounds(null, null, icon, null) + } + private fun getShareIcon(): Drawable? { val normal = app.uiUtils.getActiveIcon(R.drawable.ic_action_share) if (Build.VERSION.SDK_INT >= 21) { @@ -252,9 +272,27 @@ class UserGpxInfoFragment : BaseDialogFragment() { return normal } + private fun getLiveTrackBtnIcon(enabled: Boolean): Drawable? { + val iconColor = if (enabled) R.color.live_track_active_icon else R.color.icon_light + + val layers = arrayOfNulls(2) + layers[0] = app.uiUtils.getIcon(R.drawable.ic_action_round_shape) + layers[1] = app.uiUtils.getIcon(R.drawable.ic_action_record, iconColor) + + if (Build.VERSION.SDK_INT >= 21 && !enabled) { + val normal = layers[1] + val active = app.uiUtils.getIcon(R.drawable.ic_action_record, R.color.live_track_active_icon) + if (normal != null && active != null) { + layers[1] = AndroidUtils.createPressedStateListDrawable(normal, active) + } + } + + return LayerDrawable(layers) + } + private fun updateGpxInfo() { checkTime() - locationMessages = app.locationMessages.getMessagesForUserInChat(userId, chatId,deviceName, startCalendar.timeInMillis, endCalendar.timeInMillis) + locationMessages = app.locationMessages.getMessagesForUserInChat(userId, chatId, deviceName, startCalendar.timeInMillis, endCalendar.timeInMillis) gpxFile = OsmandLocationUtils.convertLocationMessagesToGpxFiles(locationMessages).firstOrNull()?:GPXUtilities.GPXFile() updateGPXStatisticRow()