OsmAnd/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt

857 lines
27 KiB
Kotlin
Raw Normal View History

package net.osmand.telegram
import android.content.Context
2018-10-23 11:21:15 +02:00
import android.location.LocationManager
2018-10-12 18:17:38 +02:00
import android.support.annotation.ColorRes
import android.support.annotation.DrawableRes
import android.support.annotation.StringRes
2018-10-12 18:17:38 +02:00
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import net.osmand.telegram.helpers.OsmandAidlHelper
2018-07-13 14:53:58 +02:00
import net.osmand.telegram.helpers.TelegramHelper
import net.osmand.telegram.utils.AndroidUtils
import net.osmand.telegram.utils.OsmandApiUtils
import net.osmand.telegram.utils.OsmandFormatter
import net.osmand.telegram.utils.OsmandFormatter.MetricsConstants
import net.osmand.telegram.utils.OsmandFormatter.SpeedConstants
2018-10-08 17:33:59 +02:00
import org.drinkless.td.libcore.telegram.TdApi
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
2018-10-12 18:17:38 +02:00
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentLinkedQueue
val ADDITIONAL_ACTIVE_TIME_VALUES_SEC = listOf(15 * 60L, 30 * 60L, 60 * 60L, 180 * 60L)
const val SHARE_DEVICES_KEY = "devices"
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 =
listOf(1 * 60L, 2 * 60L, 5 * 60L, 10 * 60L, 15 * 60L, 30 * 60L, 60 * 60L)
private val LOC_HISTORY_VALUES_SEC = listOf(
5 * 60L,
15 * 60L,
30 * 60L,
1 * 60 * 60L,
2 * 60 * 60L,
3 * 60 * 60L,
5 * 60 * 60L,
8 * 60 * 60L,
12 * 60 * 60L,
24 * 60 * 60L
)
const val SHARE_TYPE_MAP = "Map"
const val SHARE_TYPE_TEXT = "Text"
const val SHARE_TYPE_MAP_AND_TEXT = "Map and text"
private val SHARE_TYPE_VALUES = listOf(SHARE_TYPE_MAP, SHARE_TYPE_TEXT, SHARE_TYPE_MAP_AND_TEXT)
private const val SEND_MY_LOC_DEFAULT_INDEX = 6
private const val STALE_LOC_DEFAULT_INDEX = 0
private const val LOC_HISTORY_DEFAULT_INDEX = 7
private const val SHARE_TYPE_DEFAULT_INDEX = 2
private const val SETTINGS_NAME = "osmand_telegram_settings"
private const val SHARE_LOCATION_CHATS_KEY = "share_location_chats"
2018-09-05 11:58:32 +02:00
private const val HIDDEN_ON_MAP_CHATS_KEY = "hidden_on_map_chats"
2018-06-11 18:57:33 +02:00
private const val SHARING_MODE_KEY = "current_sharing_mode"
private const val METRICS_CONSTANTS_KEY = "metrics_constants"
private const val SPEED_CONSTANTS_KEY = "speed_constants"
private const val SEND_MY_LOC_INTERVAL_KEY = "send_my_loc_interval"
private const val STALE_LOC_TIME_KEY = "stale_loc_time"
private const val LOC_HISTORY_TIME_KEY = "loc_history_time"
private const val SHARE_TYPE_KEY = "share_type"
2018-07-13 15:28:37 +02:00
private const val APP_TO_CONNECT_PACKAGE_KEY = "app_to_connect_package"
2018-07-13 14:53:58 +02:00
private const val DEFAULT_VISIBLE_TIME_SECONDS = 60 * 60L // 1 hour
2018-07-13 13:32:11 +02:00
private const val TITLES_REPLACED_WITH_IDS = "changed_to_chat_id"
2018-09-04 16:43:42 +02:00
private const val LIVE_NOW_SORT_TYPE_KEY = "live_now_sort_type"
2018-09-04 15:43:27 +02:00
2018-10-08 17:33:59 +02:00
private const val SHARE_CHATS_INFO_KEY = "share_chats_info"
private const val BATTERY_OPTIMISATION_ASKED = "battery_optimisation_asked"
2018-10-23 11:21:15 +02:00
private const val SHARING_INITIALIZATION_TIME = 60 * 2L // 2 minutes
2018-10-29 14:57:57 +01:00
private const val GPS_UPDATE_EXPIRED_TIME = 60 * 3L // 3 minutes
class TelegramSettings(private val app: TelegramApplication) {
2018-06-11 18:57:33 +02:00
2018-10-12 18:17:38 +02:00
private var shareChatsInfo = ConcurrentHashMap<Long, ShareChatInfo>()
2018-09-05 11:58:32 +02:00
private var hiddenOnMapChats: Set<Long> = emptySet()
private var shareDevices: Set<DeviceBot> = emptySet()
2018-06-11 18:57:33 +02:00
2018-10-12 18:17:38 +02:00
var sharingStatusChanges = ConcurrentLinkedQueue<SharingStatus>()
2018-10-03 11:25:42 +02:00
var currentSharingMode = ""
private set
2018-10-02 12:01:26 +02:00
2018-06-11 18:57:33 +02:00
var metricsConstants = MetricsConstants.KILOMETERS_AND_METERS
var speedConstants = SpeedConstants.KILOMETERS_PER_HOUR
var sendMyLocInterval = SEND_MY_LOC_VALUES_SEC[SEND_MY_LOC_DEFAULT_INDEX]
var staleLocTime = STALE_LOC_VALUES_SEC[STALE_LOC_DEFAULT_INDEX]
var locHistoryTime = LOC_HISTORY_VALUES_SEC[LOC_HISTORY_DEFAULT_INDEX]
var shareTypeValue = SHARE_TYPE_VALUES[SHARE_TYPE_DEFAULT_INDEX]
2018-06-11 18:57:33 +02:00
var appToConnectPackage = ""
private set
2018-09-04 16:43:42 +02:00
var liveNowSortType = LiveNowSortType.SORT_BY_GROUP
2018-09-04 15:43:27 +02:00
val gpsAndLocPrefs = listOf(SendMyLocPref(), StaleLocPref(), LocHistoryPref(), ShareTypePref())
var batteryOptimisationAsked = false
2018-06-11 18:57:33 +02:00
init {
2018-07-13 13:32:11 +02:00
updatePrefs()
2018-06-11 18:57:33 +02:00
read()
}
2018-10-08 17:33:59 +02:00
fun hasAnyChatToShareLocation() = shareChatsInfo.isNotEmpty()
2018-06-11 18:57:33 +02:00
2018-10-12 18:17:38 +02:00
fun isSharingLocationToChat(chatId: Long) = shareChatsInfo.containsKey(chatId)
2018-06-11 18:57:33 +02:00
fun isSharingLocationToUser(userId: Int) = shareChatsInfo.values.any { it.userId == userId }
2018-09-05 11:58:32 +02:00
fun hasAnyChatToShowOnMap() = !hiddenOnMapChats.containsAll(getLiveNowChats())
2018-06-11 18:57:33 +02:00
2018-09-05 11:58:32 +02:00
fun isShowingChatOnMap(chatId: Long) = !hiddenOnMapChats.contains(chatId)
2018-06-11 18:57:33 +02:00
2018-07-13 13:02:59 +02:00
fun removeNonexistingChats(presentChatIds: List<Long>) {
2018-09-05 11:58:32 +02:00
val hiddenChats = hiddenOnMapChats.toMutableList()
hiddenChats.intersect(presentChatIds)
hiddenOnMapChats = hiddenChats.toHashSet()
2018-07-13 14:53:58 +02:00
2018-10-17 11:55:26 +02:00
shareChatsInfo = ConcurrentHashMap(shareChatsInfo.filter { (key, _) -> presentChatIds.contains(key) })
2018-06-11 18:57:33 +02:00
}
fun shareLocationToChat(
chatId: Long,
share: Boolean,
livePeriod: Long = DEFAULT_VISIBLE_TIME_SECONDS,
2018-10-12 11:08:27 +02:00
addActiveTime: Long = ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0]
) {
2018-06-11 18:57:33 +02:00
if (share) {
2018-10-08 17:33:59 +02:00
var shareChatInfo = shareChatsInfo[chatId]
if (shareChatInfo == null) {
shareChatInfo = ShareChatInfo()
}
val chat = app.telegramHelper.getChat(chatId)
if (chat != null && (chat.type is TdApi.ChatTypePrivate || chat.type is TdApi.ChatTypeSecret)) {
shareChatInfo.userId = app.telegramHelper.getUserIdFromChatType(chat.type)
}
2018-10-12 18:17:38 +02:00
shareChatInfo.chatId = chatId
updateChatShareInfo(shareChatInfo, livePeriod, addActiveTime)
2018-10-08 17:33:59 +02:00
shareChatsInfo[chatId] = shareChatInfo
2018-06-11 18:57:33 +02:00
} else {
2018-10-08 17:33:59 +02:00
shareChatsInfo.remove(chatId)
2018-06-11 18:57:33 +02:00
}
2018-07-13 14:53:58 +02:00
}
fun shareLocationToUser(
userId: Int,
livePeriod: Long = DEFAULT_VISIBLE_TIME_SECONDS,
addActiveTime: Long = ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0]
) {
val shareChatInfo = ShareChatInfo()
shareChatInfo.userId = userId
updateChatShareInfo(shareChatInfo, livePeriod, addActiveTime)
app.telegramHelper.createPrivateChatWithUser(userId, shareChatInfo, shareChatsInfo)
}
fun updateShareDevices(list: List<DeviceBot>) {
shareDevices = list.toHashSet()
2018-10-02 12:01:26 +02:00
}
2018-10-08 17:33:59 +02:00
fun addShareDevice(device: DeviceBot) {
val devices = shareDevices.toMutableList()
devices.add(device)
shareDevices = devices.toHashSet()
}
fun updateCurrentSharingMode(sharingMode: String) {
if (currentSharingMode != sharingMode) {
shareChatsInfo.forEach { (_, shareInfo) ->
shareInfo.shouldSendViaBotMessage = true
}
}
currentSharingMode = sharingMode
}
2018-10-08 17:33:59 +02:00
fun getChatLivePeriod(chatId: Long) = shareChatsInfo[chatId]?.livePeriod
fun getChatsShareInfo() = shareChatsInfo
2018-06-11 18:57:33 +02:00
fun getShareDevices() = shareDevices
fun containsShareDeviceWithName(name: String): Boolean {
shareDevices.forEach {
if (it.deviceName == name) {
return true
}
}
return false
}
fun getShareDeviceNameWithExternalId(externalId: String): String? {
return shareDevices.singleOrNull { it.externalId == externalId }?.deviceName
}
2018-10-12 18:17:38 +02:00
fun getLastSuccessfulSendTime() = shareChatsInfo.values.maxBy { it.lastSuccessfulSendTimeMs }?.lastSuccessfulSendTimeMs ?: -1
fun stopSharingLocationToChats() {
2018-10-08 17:33:59 +02:00
shareChatsInfo.clear()
}
2018-07-13 13:32:11 +02:00
fun showChatOnMap(chatId: Long, show: Boolean) {
2018-09-05 11:58:32 +02:00
val hiddenChats = hiddenOnMapChats.toMutableList()
2018-06-11 18:57:33 +02:00
if (show) {
2018-09-05 11:58:32 +02:00
hiddenChats.remove(chatId)
2018-06-11 18:57:33 +02:00
} else {
2018-09-05 11:58:32 +02:00
hiddenChats.add(chatId)
2018-06-11 18:57:33 +02:00
}
2018-09-05 11:58:32 +02:00
hiddenOnMapChats = hiddenChats.toHashSet()
2018-06-11 18:57:33 +02:00
}
2018-10-08 17:33:59 +02:00
fun getShareLocationChats() = shareChatsInfo.keys
2018-07-04 15:00:51 +02:00
2018-09-05 11:58:32 +02:00
fun getShowOnMapChats() = getLiveNowChats().minus(hiddenOnMapChats)
2018-06-11 18:57:33 +02:00
2018-09-05 11:58:32 +02:00
fun getShowOnMapChatsCount() = getShowOnMapChats().size
2018-06-11 18:57:33 +02:00
fun clear() {
stopSharingLocationToChats()
2018-08-28 11:50:49 +02:00
app.getSharedPreferences(SETTINGS_NAME, Context.MODE_PRIVATE).edit().clear().apply()
}
fun updateAppToConnect(appToConnectPackage: String) {
app.showLocationHelper.stopShowingLocation()
this.appToConnectPackage = appToConnectPackage
app.osmandAidlHelper.reconnectOsmand()
}
2018-10-08 17:33:59 +02:00
fun updateShareInfo(message: TdApi.Message) {
val shareChatInfo = shareChatsInfo[message.chatId]
val content = message.content
if (shareChatInfo != null) {
2018-12-10 14:10:11 +01:00
when (content) {
is TdApi.MessageLocation -> shareChatInfo.currentMapMessageId = message.id
is TdApi.MessageText -> shareChatInfo.currentTextMessageId = message.id
}
2018-12-10 14:10:11 +01:00
shareChatInfo.lastSuccessfulSendTimeMs = Math.max(message.editDate, message.date) * 1000L
2018-10-12 18:17:38 +02:00
}
}
fun updateSharingStatusHistory() {
2018-10-23 11:21:15 +02:00
val newSharingStatus = getNewSharingStatusHistoryItem()
2018-10-12 18:17:38 +02:00
if (sharingStatusChanges.isNotEmpty()) {
val lastSharingStatus = sharingStatusChanges.last()
if (lastSharingStatus.statusType != newSharingStatus.statusType) {
sharingStatusChanges.add(newSharingStatus)
} else {
lastSharingStatus.apply {
statusChangeTime = newSharingStatus.statusChangeTime
locationTime = newSharingStatus.locationTime
chatsTitles = newSharingStatus.chatsTitles
title = newSharingStatus.title
2018-10-23 11:21:15 +02:00
if (statusType == SharingStatusType.INITIALIZING
&& newSharingStatus.statusType == SharingStatusType.INITIALIZING) {
if (!description.contains(newSharingStatus.description)) {
description = "$description, ${newSharingStatus.description}"
}
} else {
description = newSharingStatus.description
2018-10-23 11:21:15 +02:00
}
2018-10-12 18:17:38 +02:00
}
}
} else {
sharingStatusChanges.add(newSharingStatus)
2018-10-08 17:33:59 +02:00
}
}
private fun updateChatShareInfo(
shareChatInfo: ShareChatInfo,
livePeriod: Long = DEFAULT_VISIBLE_TIME_SECONDS,
addActiveTime: Long = ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0]
) {
val lp: Long = when {
livePeriod < TelegramHelper.MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC -> TelegramHelper.MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC.toLong()
else -> livePeriod
}
val currentTime = System.currentTimeMillis() / 1000
val user = app.telegramHelper.getCurrentUser()
if (user != null && currentSharingMode != user.id.toString() && shareChatInfo.start == -1L) {
shareChatInfo.shouldSendViaBotMessage = true
}
shareChatInfo.start = currentTime
if (shareChatInfo.livePeriod == -1L) {
shareChatInfo.livePeriod = lp
}
shareChatInfo.userSetLivePeriod = lp
shareChatInfo.userSetLivePeriodStart = currentTime
shareChatInfo.currentMessageLimit = currentTime + Math.min(lp, TelegramHelper.MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC.toLong())
shareChatInfo.additionalActiveTime = addActiveTime
}
2018-10-23 11:21:15 +02:00
private fun getNewSharingStatusHistoryItem(): SharingStatus {
return SharingStatus().apply {
statusChangeTime = System.currentTimeMillis()
val lm = app.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val gpsEnabled = try {
if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
val loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER)
2018-10-29 15:50:24 +01:00
val gpsActive = loc != null && ((statusChangeTime - loc.time) / 1000) < GPS_UPDATE_EXPIRED_TIME
val lastSentLocationExpired = ((statusChangeTime - app.shareLocationHelper.lastLocationMessageSentTime) / 1000) > GPS_UPDATE_EXPIRED_TIME
(gpsActive || !lastSentLocationExpired)
} else {
false
}
2018-10-23 11:21:15 +02:00
} catch (ex: Exception) {
false
}
var initializing = false
var sendChatsErrors = false
shareChatsInfo.forEach { (_, shareInfo) ->
if (shareInfo.lastSuccessfulSendTimeMs == -1L && ((statusChangeTime / 1000 - shareInfo.start) < SHARING_INITIALIZATION_TIME)) {
initializing = true
}
if (shareInfo.hasSharingError) {
sendChatsErrors = true
locationTime = shareInfo.lastSuccessfulSendTimeMs
val title = app.telegramHelper.getChat(shareInfo.chatId)?.title
if (title != null) {
chatsTitles.add(title)
}
}
}
if (sendChatsErrors) {
title = app.getString(R.string.not_possible_to_send_to_telegram_chats)
description = app.getString(R.string.last_updated_location)
statusType = SharingStatusType.NOT_POSSIBLE_TO_SENT_TO_CHATS
} else if (!initializing) {
when {
!gpsEnabled -> {
locationTime = app.shareLocationHelper.lastLocationMessageSentTime
if (locationTime <= 0) {
locationTime = getLastSuccessfulSendTime()
}
2018-10-23 11:21:15 +02:00
title = app.getString(R.string.no_gps_connection)
description = app.getString(R.string.last_updated_location)
statusType = SharingStatusType.NO_GPS
}
!app.isInternetConnectionAvailable -> {
locationTime = getLastSuccessfulSendTime()
title = app.getString(R.string.no_internet_connection)
description = app.getString(R.string.last_updated_location)
statusType = SharingStatusType.NO_INTERNET
}
else -> {
locationTime = getLastSuccessfulSendTime()
2018-10-25 16:37:01 +02:00
statusType = SharingStatusType.SENDING
2018-10-25 16:34:57 +02:00
if (locationTime == -1L) {
title = app.getString(R.string.sending_location_messages)
description = app.getString(R.string.waiting_for_response_from_telegram)
} else {
title = app.getString(R.string.successfully_sent_and_updated)
description = app.getString(R.string.last_updated_location)
}
2018-10-23 11:21:15 +02:00
}
}
} else {
2018-10-23 11:36:28 +02:00
if (gpsEnabled && app.isInternetConnectionAvailable) {
title = app.getString(R.string.sending_location_messages)
description = app.getString(R.string.waiting_for_response_from_telegram)
statusType = SharingStatusType.SENDING
} else {
title = app.getString(R.string.initializing)
statusType = SharingStatusType.INITIALIZING
if (!gpsEnabled) {
2018-10-23 11:21:15 +02:00
description = app.getString(R.string.searching_for_gps)
2018-10-23 11:36:28 +02:00
} else if (!app.isInternetConnectionAvailable) {
2018-10-23 11:21:15 +02:00
description = app.getString(R.string.connecting_to_the_internet)
}
}
}
}
}
2018-10-08 17:33:59 +02:00
fun onDeleteLiveMessages(chatId: Long, messages: List<Long>) {
val currentMapMessageId = shareChatsInfo[chatId]?.currentMapMessageId
if (messages.contains(currentMapMessageId)) {
shareChatsInfo[chatId]?.currentMapMessageId = -1
}
val currentTextMessageId = shareChatsInfo[chatId]?.currentTextMessageId
if (messages.contains(currentTextMessageId)) {
shareChatsInfo[chatId]?.currentTextMessageId = -1
shareChatsInfo[chatId]?.updateTextMessageId = 1
2018-10-08 17:33:59 +02:00
}
}
2018-06-11 18:57:33 +02:00
fun save() {
val prefs = app.getSharedPreferences(SETTINGS_NAME, Context.MODE_PRIVATE)
val edit = prefs.edit()
2018-09-05 11:58:32 +02:00
val hiddenChatsSet = mutableSetOf<String>()
val hiddenChats = ArrayList(hiddenOnMapChats)
for (chatId in hiddenChats) {
hiddenChatsSet.add(chatId.toString())
2018-06-11 18:57:33 +02:00
}
2018-09-05 11:58:32 +02:00
edit.putStringSet(HIDDEN_ON_MAP_CHATS_KEY, hiddenChatsSet)
2018-06-11 18:57:33 +02:00
edit.putString(SHARING_MODE_KEY, currentSharingMode)
2018-06-11 18:57:33 +02:00
edit.putString(METRICS_CONSTANTS_KEY, metricsConstants.name)
edit.putString(SPEED_CONSTANTS_KEY, speedConstants.name)
edit.putLong(SEND_MY_LOC_INTERVAL_KEY, sendMyLocInterval)
edit.putLong(STALE_LOC_TIME_KEY, staleLocTime)
edit.putLong(LOC_HISTORY_TIME_KEY, locHistoryTime)
2018-06-11 18:57:33 +02:00
edit.putString(SHARE_TYPE_KEY, shareTypeValue)
edit.putString(APP_TO_CONNECT_PACKAGE_KEY, appToConnectPackage)
2018-09-04 16:43:42 +02:00
edit.putString(LIVE_NOW_SORT_TYPE_KEY, liveNowSortType.name)
edit.putBoolean(BATTERY_OPTIMISATION_ASKED, batteryOptimisationAsked)
val jArray = convertShareChatsInfoToJson()
if (jArray != null) {
2018-10-08 17:33:59 +02:00
edit.putString(SHARE_CHATS_INFO_KEY, jArray.toString())
}
val jsonObject = convertShareDevicesToJson()
if (jsonObject != null) {
edit.putString(SHARE_DEVICES_KEY, jsonObject.toString())
}
2018-06-11 18:57:33 +02:00
edit.apply()
}
fun read() {
val prefs = app.getSharedPreferences(SETTINGS_NAME, Context.MODE_PRIVATE)
2018-09-05 11:58:32 +02:00
val hiddenChats = mutableSetOf<Long>()
val hiddenChatsSet = prefs.getStringSet(HIDDEN_ON_MAP_CHATS_KEY, mutableSetOf())
for (chatId in hiddenChatsSet) {
hiddenChats.add(chatId.toLong())
2018-06-11 18:57:33 +02:00
}
2018-09-05 11:58:32 +02:00
hiddenOnMapChats = hiddenChats
2018-06-11 18:57:33 +02:00
2018-07-04 15:00:51 +02:00
metricsConstants = MetricsConstants.valueOf(
2018-07-13 13:32:11 +02:00
prefs.getString(METRICS_CONSTANTS_KEY, MetricsConstants.KILOMETERS_AND_METERS.name)
2018-07-04 15:00:51 +02:00
)
speedConstants = SpeedConstants.valueOf(
2018-07-13 13:32:11 +02:00
prefs.getString(SPEED_CONSTANTS_KEY, SpeedConstants.KILOMETERS_PER_HOUR.name)
2018-07-04 15:00:51 +02:00
)
2018-10-08 17:33:59 +02:00
try {
parseShareChatsInfo(JSONArray(prefs.getString(SHARE_CHATS_INFO_KEY, "")))
} catch (e: JSONException) {
e.printStackTrace()
}
parseShareDevices(prefs.getString(SHARE_DEVICES_KEY, ""))
val sendMyLocDef = SEND_MY_LOC_VALUES_SEC[SEND_MY_LOC_DEFAULT_INDEX]
sendMyLocInterval = prefs.getLong(SEND_MY_LOC_INTERVAL_KEY, sendMyLocDef)
val staleLocDef = STALE_LOC_VALUES_SEC[STALE_LOC_DEFAULT_INDEX]
staleLocTime = prefs.getLong(STALE_LOC_TIME_KEY, staleLocDef)
val locHistoryDef = LOC_HISTORY_VALUES_SEC[LOC_HISTORY_DEFAULT_INDEX]
locHistoryTime = prefs.getLong(LOC_HISTORY_TIME_KEY, locHistoryDef)
val shareTypeDef = SHARE_TYPE_VALUES[SHARE_TYPE_DEFAULT_INDEX]
shareTypeValue = prefs.getString(SHARE_TYPE_KEY, shareTypeDef)
currentSharingMode = prefs.getString(SHARING_MODE_KEY, "")
appToConnectPackage = prefs.getString(APP_TO_CONNECT_PACKAGE_KEY, "")
liveNowSortType = LiveNowSortType.valueOf(
prefs.getString(LIVE_NOW_SORT_TYPE_KEY, LiveNowSortType.SORT_BY_GROUP.name)
)
batteryOptimisationAsked = prefs.getBoolean(BATTERY_OPTIMISATION_ASKED,false)
2018-06-11 18:57:33 +02:00
}
2018-07-13 13:32:11 +02:00
private fun convertShareDevicesToJson():JSONObject?{
return try {
val jsonObject = JSONObject()
val jArray = JSONArray()
shareDevices.forEach { device ->
val obj = JSONObject()
obj.put(DeviceBot.DEVICE_ID, device.id)
obj.put(DeviceBot.USER_ID, device.userId)
obj.put(DeviceBot.CHAT_ID, device.chatId)
obj.put(DeviceBot.DEVICE_NAME, device.deviceName)
obj.put(DeviceBot.EXTERNAL_ID, device.externalId)
obj.put(DeviceBot.DATA, JSONObject(device.data))
jArray.put(obj)
}
jsonObject.put(SHARE_DEVICES_KEY, jArray)
} catch (e: JSONException) {
e.printStackTrace()
null
}
}
private fun convertShareChatsInfoToJson(): JSONArray? {
return try {
val jArray = JSONArray()
shareChatsInfo.forEach { (chatId, chatInfo) ->
val obj = JSONObject()
obj.put(ShareChatInfo.CHAT_ID_KEY, chatId)
obj.put(ShareChatInfo.USER_ID_KEY, chatInfo.userId)
obj.put(ShareChatInfo.START_KEY, chatInfo.start)
obj.put(ShareChatInfo.LIVE_PERIOD_KEY, chatInfo.livePeriod)
obj.put(ShareChatInfo.LIMIT_KEY, chatInfo.currentMessageLimit)
obj.put(ShareChatInfo.UPDATE_TEXT_MESSAGE_ID_KEY, chatInfo.updateTextMessageId)
obj.put(ShareChatInfo.CURRENT_MAP_MESSAGE_ID_KEY, chatInfo.currentMapMessageId)
obj.put(ShareChatInfo.CURRENT_TEXT_MESSAGE_ID_KEY, chatInfo.currentTextMessageId)
obj.put(ShareChatInfo.USER_SET_LIVE_PERIOD_KEY, chatInfo.userSetLivePeriod)
obj.put(ShareChatInfo.USER_SET_LIVE_PERIOD_START_KEY, chatInfo.userSetLivePeriodStart)
obj.put(ShareChatInfo.LAST_SUCCESSFUL_SEND_TIME_KEY, chatInfo.lastSuccessfulSendTimeMs)
jArray.put(obj)
}
jArray
} catch (e: JSONException) {
e.printStackTrace()
null
}
}
2018-10-08 17:33:59 +02:00
private fun parseShareChatsInfo(json: JSONArray) {
for (i in 0 until json.length()) {
val obj = json.getJSONObject(i)
val shareInfo = ShareChatInfo().apply {
chatId = obj.optLong(ShareChatInfo.CHAT_ID_KEY)
userId = obj.optInt(ShareChatInfo.USER_ID_KEY)
2018-10-08 17:33:59 +02:00
start = obj.optLong(ShareChatInfo.START_KEY)
livePeriod = obj.optLong(ShareChatInfo.LIVE_PERIOD_KEY)
currentMessageLimit = obj.optLong(ShareChatInfo.LIMIT_KEY)
updateTextMessageId = obj.optInt(ShareChatInfo.UPDATE_TEXT_MESSAGE_ID_KEY)
currentMapMessageId = obj.optLong(ShareChatInfo.CURRENT_MAP_MESSAGE_ID_KEY)
currentTextMessageId = obj.optLong(ShareChatInfo.CURRENT_TEXT_MESSAGE_ID_KEY)
2018-10-08 17:33:59 +02:00
userSetLivePeriod = obj.optLong(ShareChatInfo.USER_SET_LIVE_PERIOD_KEY)
userSetLivePeriodStart = obj.optLong(ShareChatInfo.USER_SET_LIVE_PERIOD_START_KEY)
lastSuccessfulSendTimeMs = obj.optLong(ShareChatInfo.LAST_SUCCESSFUL_SEND_TIME_KEY)
2018-10-08 17:33:59 +02:00
}
shareChatsInfo[shareInfo.chatId] = shareInfo
}
}
private fun parseShareDevices(json: String) {
shareDevices = OsmandApiUtils.parseJsonContents(json).toHashSet()
}
2018-09-05 11:58:32 +02:00
private fun getLiveNowChats() = app.telegramHelper.getMessagesByChatIds(locHistoryTime).keys
2018-07-13 13:32:11 +02:00
private fun updatePrefs() {
val prefs = app.getSharedPreferences(SETTINGS_NAME, Context.MODE_PRIVATE)
val idsInUse = prefs.getBoolean(TITLES_REPLACED_WITH_IDS, false)
if (!idsInUse) {
val edit = prefs.edit()
edit.putStringSet(SHARE_LOCATION_CHATS_KEY, emptySet())
edit.putBoolean(TITLES_REPLACED_WITH_IDS, true)
edit.apply()
}
}
inner class SendMyLocPref : DurationPref(
R.drawable.ic_action_share_location,
R.string.send_my_location,
R.string.send_my_location_desc,
SEND_MY_LOC_VALUES_SEC
) {
override fun getCurrentValue() =
OsmandFormatter.getFormattedDuration(app, sendMyLocInterval)
override fun setCurrentValue(index: Int) {
sendMyLocInterval = values[index]
app.updateSendLocationInterval()
}
}
inner class StaleLocPref : DurationPref(
R.drawable.ic_action_time_span,
R.string.stale_location,
R.string.stale_location_desc,
STALE_LOC_VALUES_SEC
) {
override fun getCurrentValue() =
OsmandFormatter.getFormattedDuration(app, staleLocTime)
override fun setCurrentValue(index: Int) {
staleLocTime = values[index]
}
}
inner class LocHistoryPref : DurationPref(
R.drawable.ic_action_location_history,
R.string.location_history,
R.string.location_history_desc,
LOC_HISTORY_VALUES_SEC
) {
override fun getCurrentValue() =
OsmandFormatter.getFormattedDuration(app, locHistoryTime)
override fun setCurrentValue(index: Int) {
val value = values[index]
locHistoryTime = value
app.telegramHelper.messageActiveTimeSec = value
}
}
inner class ShareTypePref : DurationPref(
R.drawable.ic_action_location_history,
R.string.location_history,
R.string.location_history_desc,
emptyList()
) {
override fun getCurrentValue(): String {
return when (shareTypeValue) {
SHARE_TYPE_MAP -> "Map"
SHARE_TYPE_TEXT -> "Text"
SHARE_TYPE_MAP_AND_TEXT -> "Map and text"
else -> ""
}
}
override fun setCurrentValue(index: Int) {
shareTypeValue = SHARE_TYPE_VALUES[index]
}
override fun getMenuItems() = SHARE_TYPE_VALUES
}
abstract inner class DurationPref(
@DrawableRes val iconId: Int,
@StringRes val titleId: Int,
@StringRes val descriptionId: Int,
val values: List<Long>
) {
abstract fun getCurrentValue(): String
abstract fun setCurrentValue(index: Int)
open fun getMenuItems() = values.map { OsmandFormatter.getFormattedDuration(app, it) }
}
enum class AppConnect(
@DrawableRes val iconId: Int,
@DrawableRes val whiteIconId: Int,
val title: String,
2018-09-03 13:30:40 +02:00
val appPackage: String,
val showOnlyInstalled: Boolean
) {
OSMAND_PLUS(
R.drawable.ic_logo_osmand_plus,
R.drawable.ic_action_osmand_plus,
"OsmAnd+",
2018-09-03 13:30:40 +02:00
OsmandAidlHelper.OSMAND_PLUS_PACKAGE_NAME,
false
),
OSMAND_FREE(
R.drawable.ic_logo_osmand_free,
R.drawable.ic_action_osmand_free,
"OsmAnd",
2018-09-03 13:30:40 +02:00
OsmandAidlHelper.OSMAND_FREE_PACKAGE_NAME,
false
),
OSMAND_NIGHTLY(
2018-09-03 14:58:51 +02:00
R.drawable.ic_logo_osmand_nightly,
2018-09-03 13:30:40 +02:00
R.drawable.ic_action_osmand_free,
"OsmAnd Nightly",
OsmandAidlHelper.OSMAND_NIGHTLY_PACKAGE_NAME,
true
);
companion object {
@DrawableRes
fun getWhiteIconId(appPackage: String): Int {
for (item in values()) {
if (item.appPackage == appPackage) {
return item.whiteIconId
}
}
return 0
}
fun getInstalledApps(context: Context) =
values().filter { AndroidUtils.isAppInstalled(context, it.appPackage) }
}
}
2018-09-04 16:43:42 +02:00
enum class LiveNowSortType(
@DrawableRes val iconId: Int,
@StringRes val titleId: Int,
@StringRes val shortTitleId: Int
) {
2018-09-04 16:43:42 +02:00
SORT_BY_GROUP(
R.drawable.ic_action_sort_by_group,
R.string.shared_string_group,
R.string.by_group
),
SORT_BY_NAME(
R.drawable.ic_action_sort_by_name,
R.string.shared_string_name,
R.string.by_name
),
SORT_BY_DISTANCE(
R.drawable.ic_action_sort_by_distance,
R.string.shared_string_distance,
R.string.by_distance
);
fun isSortByGroup() = this == SORT_BY_GROUP
}
2018-10-02 12:01:26 +02:00
2018-10-12 18:17:38 +02:00
enum class SharingStatusType(
@DrawableRes val iconId: Int,
@ColorRes val iconColorRes: Int,
val canResendLocation: Boolean
) {
NO_INTERNET(
R.drawable.ic_action_wifi_off,
R.color.sharing_status_icon_error,
true
),
2018-10-23 11:21:15 +02:00
SENDING(
R.drawable.ic_action_share_location,
R.color.sharing_status_icon_success,
2018-10-12 18:17:38 +02:00
false
),
NOT_POSSIBLE_TO_SENT_TO_CHATS(
R.drawable.ic_action_message_send_error,
R.color.sharing_status_icon_error,
true
),
NO_GPS(
R.drawable.ic_action_location_off,
R.color.sharing_status_icon_error,
2018-10-23 11:21:15 +02:00
false
),
INITIALIZING(
R.drawable.ic_action_connect,
R.color.sharing_status_icon_error,
2018-10-12 18:17:38 +02:00
false
);
}
2018-10-02 12:01:26 +02:00
class DeviceBot {
var id: Long = -1
var userId: Long = -1
var chatId: Long = -1
var deviceName: String = ""
var externalId: String = ""
var data: String = ""
companion object {
internal const val DEVICE_ID = "id"
internal const val USER_ID = "userId"
internal const val CHAT_ID = "chatId"
internal const val DEVICE_NAME = "deviceName"
internal const val EXTERNAL_ID = "externalId"
internal const val DATA = "data"
}
2018-10-02 12:01:26 +02:00
}
2018-10-08 17:33:59 +02:00
2018-10-12 18:17:38 +02:00
class SharingStatus {
2018-10-23 11:21:15 +02:00
var title: String = ""
var description: String = ""
2018-10-12 18:17:38 +02:00
var locationTime: Long = -1
var statusChangeTime: Long = -1
var chatsTitles: MutableList<String> = mutableListOf()
2018-10-23 11:21:15 +02:00
2018-10-12 18:17:38 +02:00
lateinit var statusType: SharingStatusType
2018-10-23 11:21:15 +02:00
fun getTitle(app: TelegramApplication): CharSequence {
2018-10-12 18:17:38 +02:00
return if (statusType != SharingStatusType.NOT_POSSIBLE_TO_SENT_TO_CHATS || chatsTitles.isEmpty()) {
2018-10-23 11:21:15 +02:00
title
2018-10-12 18:17:38 +02:00
} else {
2018-10-23 11:21:15 +02:00
val spannableString = SpannableStringBuilder(title)
2018-10-12 18:17:38 +02:00
val iterator = chatsTitles.iterator()
while (iterator.hasNext()) {
val chatTitle = iterator.next()
val start = spannableString.length
val newSpannable = if (iterator.hasNext()) " @$chatTitle," else " @$chatTitle."
spannableString.append(newSpannable)
2018-10-16 17:42:43 +02:00
spannableString.setSpan(ForegroundColorSpan(app.uiUtils.getActiveColor()), start, spannableString.length - 1, 0)
2018-10-12 18:17:38 +02:00
}
spannableString
}
}
}
2018-10-08 17:33:59 +02:00
class ShareChatInfo {
var chatId = -1L
var userId = -1
2018-10-08 17:33:59 +02:00
var start = -1L
var livePeriod = -1L
var updateTextMessageId = 1
2018-10-08 17:33:59 +02:00
var currentMessageLimit = -1L
var currentMapMessageId = -1L
var currentTextMessageId = -1L
2018-10-08 17:33:59 +02:00
var userSetLivePeriod = -1L
var userSetLivePeriodStart = -1L
2018-10-12 18:17:38 +02:00
var lastSuccessfulSendTimeMs = -1L
2018-10-08 17:33:59 +02:00
var shouldDeletePreviousMessage = false
var shouldSendViaBotMessage = false
2018-10-16 17:42:43 +02:00
var hasSharingError = false
var additionalActiveTime = ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0]
2018-10-16 17:42:43 +02:00
fun getNextAdditionalActiveTime(): Long {
var index = ADDITIONAL_ACTIVE_TIME_VALUES_SEC.indexOf(additionalActiveTime)
return if (ADDITIONAL_ACTIVE_TIME_VALUES_SEC.lastIndex > index) {
ADDITIONAL_ACTIVE_TIME_VALUES_SEC[++index]
} else {
ADDITIONAL_ACTIVE_TIME_VALUES_SEC[index]
}
}
fun getChatLiveMessageExpireTime(): Long {
return userSetLivePeriod - ((System.currentTimeMillis() / 1000) - start)
}
2018-10-08 17:33:59 +02:00
companion object {
internal const val CHAT_ID_KEY = "chatId"
internal const val USER_ID_KEY = "userId"
2018-10-08 17:33:59 +02:00
internal const val START_KEY = "start"
internal const val LIVE_PERIOD_KEY = "livePeriod"
internal const val LIMIT_KEY = "limit"
internal const val UPDATE_TEXT_MESSAGE_ID_KEY = "updateTextMessageId"
internal const val CURRENT_MAP_MESSAGE_ID_KEY = "currentMapMessageId"
internal const val CURRENT_TEXT_MESSAGE_ID_KEY = "currentTextMessageId"
2018-10-08 17:33:59 +02:00
internal const val USER_SET_LIVE_PERIOD_KEY = "userSetLivePeriod"
internal const val USER_SET_LIVE_PERIOD_START_KEY = "userSetLivePeriodStart"
internal const val LAST_SUCCESSFUL_SEND_TIME_KEY = "lastSuccessfulSendTime"
2018-10-08 17:33:59 +02:00
}
}
}