diff --git a/OsmAnd-telegram/res/layout/header_list_item.xml b/OsmAnd-telegram/res/layout/header_list_item.xml
new file mode 100644
index 0000000000..bb6a49e891
--- /dev/null
+++ b/OsmAnd-telegram/res/layout/header_list_item.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OsmAnd-telegram/res/layout/last_share_list_item.xml b/OsmAnd-telegram/res/layout/last_share_list_item.xml
index e6d1804f40..e72da6e6b5 100644
--- a/OsmAnd-telegram/res/layout/last_share_list_item.xml
+++ b/OsmAnd-telegram/res/layout/last_share_list_item.xml
@@ -26,8 +26,11 @@
tools:src="@drawable/img_user_picture" />
+
+
diff --git a/OsmAnd-telegram/res/values/strings.xml b/OsmAnd-telegram/res/values/strings.xml
index 05b27552e7..b4ccb58984 100644
--- a/OsmAnd-telegram/res/values/strings.xml
+++ b/OsmAnd-telegram/res/values/strings.xml
@@ -1,5 +1,6 @@
+ Suggested
Select time zone to show in your location messages.
Time zone
Units & formats
diff --git a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt
index fa056eed7b..c49a233145 100644
--- a/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt
+++ b/OsmAnd-telegram/src/net/osmand/telegram/TelegramSettings.kt
@@ -7,6 +7,7 @@ import android.support.annotation.DrawableRes
import android.support.annotation.StringRes
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
+import com.google.gson.JsonObject
import net.osmand.PlatformUtil
import net.osmand.telegram.helpers.OsmandAidlHelper
import net.osmand.telegram.helpers.ShowLocationHelper
@@ -14,13 +15,15 @@ import net.osmand.telegram.helpers.TelegramHelper
import net.osmand.telegram.utils.*
import net.osmand.telegram.utils.OsmandFormatter.MetricsConstants
import net.osmand.telegram.utils.OsmandFormatter.SpeedConstants
-import net.osmand.telegram.utils.OsmandLocationUtils
import org.drinkless.td.libcore.telegram.TdApi
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
+import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentLinkedQueue
+import kotlin.collections.ArrayList
+
val ADDITIONAL_ACTIVE_TIME_VALUES_SEC = listOf(15 * 60L, 30 * 60L, 60 * 60L, 180 * 60L)
@@ -838,6 +841,8 @@ class TelegramSettings(private val app: TelegramApplication) {
val obj = JSONObject()
obj.put(LastChatInfo.CHAT_ID_KEY, chatId)
obj.put(LastChatInfo.LIVE_PERIOD_KEY, lastInfo.livePeriod)
+ obj.put(LastChatInfo.PERIODS_KEY, convertPeriodsToJson(lastInfo.periods))
+ log.info("Periods to put: ${lastInfo.periods}")
jArray.put(obj)
}
jArray
@@ -847,6 +852,22 @@ class TelegramSettings(private val app: TelegramApplication) {
}
}
+ private fun convertPeriodsToJson(periods: LinkedList): JSONArray? {
+ return try {
+ val jArray = JSONArray()
+ for (i in 0 until periods.count()) {
+ val obj = JSONObject()
+ obj.put(i.toString(), periods[i])
+ jArray.put(obj)
+ }
+ log.info("Json array periods: $jArray")
+ jArray
+ } catch (e: JSONException) {
+ log.error(e)
+ null
+ }
+ }
+
private fun parseShareChatsInfo(json: JSONArray) {
for (i in 0 until json.length()) {
val obj = json.getJSONObject(i)
@@ -918,12 +939,59 @@ class TelegramSettings(private val app: TelegramApplication) {
val obj = json.getJSONObject(i)
val lastInfo = LastChatInfo().apply {
chatId = obj.optLong(LastChatInfo.CHAT_ID_KEY)
- livePeriod = obj.getLong(LastChatInfo.LIVE_PERIOD_KEY)
+// livePeriod = obj.optLong(LastChatInfo.LIVE_PERIOD_KEY)
+ periods = LinkedList()
+ val jsonArray = obj.getJSONArray(LastChatInfo.PERIODS_KEY)
+ log.info("getJson: $jsonArray")
+ for (j in 0 until jsonArray.length()) {
+ val obj=jsonArray.get(j) as JSONObject
+
+ periods.add(obj.optLong(j.toString()))
+ }
+ log.info("Periods: $periods")
+ livePeriod = calcLivePeriod(periods)
}
lastChatsInfo[lastInfo.chatId] = lastInfo
}
}
-
+
+ fun addTimePeriodToLastItem(id: Long, time: Long) {
+ if (lastChatsInfo.containsKey(id)) {
+ lastChatsInfo[id]?.periods = addTimeToPeriods(lastChatsInfo[id]?.periods, time)
+ } else {
+ lastChatsInfo[id] = LastChatInfo().apply {
+ chatId = id
+ livePeriod = time
+ periods = LinkedList().apply {
+ addFirst(time)
+ }
+ }
+ }
+ }
+
+ private fun addTimeToPeriods(periods: LinkedList?, time: Long): LinkedList {
+ if (periods?.isNotEmpty() != null) {
+ return if (periods.count() < 5) {
+ periods.addFirst(time)
+ periods
+ } else {
+ periods.removeLast()
+ periods.addFirst(time)
+ periods
+ }
+ }
+ return LinkedList().apply { addFirst(time) }
+ }
+
+ private fun calcLivePeriod(periods: LinkedList): Long {
+ periods.sort()
+ return if (periods.count() % 2 == 0) {
+ (periods[periods.count() / 2] + periods[periods.count() / 2 - 1]) / 2
+ } else {
+ periods[periods.count() / 2]
+ }
+ }
+
private fun getLiveNowChats() = app.telegramHelper.getMessagesByChatIds(locHistoryTime).keys
private fun updatePrefs() {
@@ -1417,10 +1485,12 @@ class TelegramSettings(private val app: TelegramApplication) {
var chatId = -1L
var livePeriod = -1L
+ var periods = LinkedList()
companion object {
internal const val CHAT_ID_KEY = "chatId"
internal const val LIVE_PERIOD_KEY = "livePeriod"
+ internal const val PERIODS_KEY = "periods"
}
}
}
\ No newline at end of file
diff --git a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt
index 288d166bc1..19eb83f802 100644
--- a/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt
+++ b/OsmAnd-telegram/src/net/osmand/telegram/helpers/TelegramUiHelper.kt
@@ -1,6 +1,8 @@
package net.osmand.telegram.helpers
import android.graphics.Bitmap
+import android.graphics.ColorMatrix
+import android.graphics.ColorMatrixColorFilter
import android.graphics.drawable.Drawable
import android.widget.ImageView
import net.osmand.data.LatLon
@@ -13,6 +15,11 @@ import org.drinkless.td.libcore.telegram.TdApi
object TelegramUiHelper {
+ fun applyGrayscaleFilter(iv: ImageView?) {
+ val matrix = ColorMatrix().apply { setSaturation(0F) }
+ iv?.colorFilter = ColorMatrixColorFilter(matrix)
+ }
+
fun setupPhoto(
app: TelegramApplication,
iv: ImageView?,
diff --git a/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt b/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt
index f6dcca9c9d..ffc99c60df 100644
--- a/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt
+++ b/OsmAnd-telegram/src/net/osmand/telegram/ui/MyLocationTabFragment.kt
@@ -3,7 +3,11 @@ package net.osmand.telegram.ui
import android.animation.*
import android.annotation.SuppressLint
import android.content.Intent
+import android.graphics.Canvas
+import android.graphics.Rect
import android.graphics.Typeface
+import android.graphics.drawable.ColorDrawable
+import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.os.Build
import android.os.Bundle
@@ -33,6 +37,7 @@ import java.util.concurrent.ConcurrentHashMap
private const val SELECTED_CHATS_KEY = "selected_chats"
private const val SELECTED_CHATS_USERS = "selected_users"
+private const val HEADER = 3
private const val LAST_SHARE_CHAT = 2
private const val SHARE_LOCATION_CHAT = 1
private const val DEFAULT_CHAT = 0
@@ -209,6 +214,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
}
})
+ addItemDecoration(createDividerItemDecoration(sharingMode))
}
mainView.findViewById(R.id.stop_all_sharing_row).setOnClickListener {
@@ -248,6 +254,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
updateCurrentUserPhoto()
updateContent()
updateEnable = true
+ settings.read()
startHandler()
}
@@ -459,6 +466,54 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
}
+ private fun createDividerItemDecoration(sharingMode: Boolean): RecyclerView.ItemDecoration {
+ val divider: Drawable = ColorDrawable(ContextCompat.getColor(app, R.color.card_divider_dark))
+ val pluginDividerHeight: Int = AndroidUtils.dpToPx(app, 1f)
+ return object : RecyclerView.ItemDecoration() {
+ override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) {
+ val dividerLeft = if (sharingMode){
+ AndroidUtils.dpToPx(app, 72f)
+ } else {
+ parent.paddingLeft
+ }
+ val dividerRight = parent.width - parent.paddingRight
+ val childCount = parent.childCount
+ for (i in 0 until childCount - 1) {
+ val child = parent.getChildAt(i)
+ if (shouldDrawDivider(i)) {
+ val params = child.layoutParams as RecyclerView.LayoutParams
+ val dividerTop = child.bottom + params.bottomMargin
+ val dividerBottom = dividerTop + pluginDividerHeight
+ divider.setBounds(dividerLeft, dividerTop, dividerRight, dividerBottom)
+ divider.draw(canvas)
+ }
+ }
+ }
+
+ override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
+ val position = parent.getChildAdapterPosition(view)
+ if (shouldDrawDivider(position)) {
+ outRect[0, 0, 0] = pluginDividerHeight
+ }
+ }
+
+ private fun shouldDrawDivider(position: Int): Boolean {
+ val item = adapter.items[position]
+ val nextP = position + 1
+ if (nextP < adapter.items.count()) {
+ val next = adapter.items[nextP]
+ if (!sharingMode && item is LastChat && next !is LastChat) {
+ return true
+ }
+ }
+ if (sharingMode && item is LastChat) {
+ return true
+ }
+ return false
+ }
+ }
+ }
+
private fun updateContent() {
sharingMode = sharingMode && settings.hasAnyChatToShareLocation()
updateSharingStatus()
@@ -493,7 +548,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
private fun updateList() {
- val items: MutableList = mutableListOf()
+ val lastItems = getLastShareItems()
+ val items: MutableList = mutableListOf()
val chats: MutableList = mutableListOf()
val contacts = telegramHelper.getContacts()
val chatList = if (sharingMode) {
@@ -521,28 +577,33 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
}
if (sharingMode && settings.hasAnyChatToShareLocation()) {
- adapter.items = sortAdapterItems(items)
+ val filteredLastItems = lastItems.filter { !settings.isSharingLocationToChat(it.chat.id) }.toMutableList()
+ val sorted = sortAdapterItems(items as MutableList)
+ if (filteredLastItems.isNotEmpty()) {
+ sorted.add(getString(R.string.shared_string_suggested))
+ }
+ sorted.addAll(filteredLastItems)
+ adapter.items = sorted
} else {
- items.addAll(0, getLastShareItems(items))
+ val filteredLastItems = lastItems.filter { !settings.isSharingLocationToChat(it.chat.id) }.toMutableList()
+ items.addAll(0, filteredLastItems)
adapter.items = items
}
}
- private fun getLastShareItems(items: MutableList): MutableList {
- val lastItems: MutableList = mutableListOf()
- items.forEach {
- val id = when (it) {
- is TdApi.Chat -> it.id
- else -> -1
- }
- if (lastChatsInfo.containsKey(id)) {
- lastItems.add(LastChat(it as TdApi.Chat, lastChatsInfo[id]!!.livePeriod))
+ private fun getLastShareItems(): MutableList {
+ val lastItems: MutableList = mutableListOf()
+ val chatListIds = telegramHelper.getChatListIds()
+ chatListIds.forEach { chatId ->
+ val chat = telegramHelper.getChat(chatId)
+ if (chat != null && lastChatsInfo.containsKey(chatId)) {
+ lastItems.add(LastChat(chat, lastChatsInfo[chatId]!!.livePeriod))
}
}
return lastItems
}
- private fun sortAdapterItems(list: MutableList): MutableList {
+ private fun sortAdapterItems(list: MutableList): MutableList {
list.sortWith(Comparator { o1, o2 ->
val title1 = when (o1) {
is TdApi.Chat -> o1.title
@@ -556,12 +617,12 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
title1.compareTo(title2)
})
- return list
+ return list.toMutableList()
}
inner class MyLocationListAdapter :
RecyclerView.Adapter() {
- var items = mutableListOf()
+ var items = mutableListOf()
set(value) {
field = value
notifyDataSetChanged()
@@ -576,6 +637,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
return if (item is LastChat) {
LAST_SHARE_CHAT
+ } else if (item is String) {
+ HEADER
} else if (settings.isSharingLocationToChat(id) && sharingMode) {
SHARE_LOCATION_CHAT
} else {
@@ -600,6 +663,11 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
.inflate(R.layout.last_share_list_item, parent, false)
LastChatViewHolder(view)
}
+ HEADER -> {
+ val view = LayoutInflater.from(parent.context)
+ .inflate(R.layout.header_list_item, parent, false)
+ HeaderViewHolder(view)
+ }
else -> throw RuntimeException("Unsupported view type: $viewType")
}
}
@@ -610,8 +678,10 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
val isChat = item is TdApi.Chat
val itemId = if (isChat) {
(item as TdApi.Chat).id
+ } else if (item is TdApi.User) {
+ item.id.toLong()
} else {
- (item as TdApi.User).id.toLong()
+ -1
}
val lastItem = position == itemCount - 1
@@ -629,6 +699,10 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
TelegramUiHelper.setupPhoto(app, holder.icon, photoPath, placeholderId, false)
+ if (item is LastChat) {
+ TelegramUiHelper.applyGrayscaleFilter(holder.icon)
+ }
+
val currentUserId = telegramHelper.getCurrentUserId()
val title = when (item) {
is LastChat -> {
@@ -705,13 +779,9 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
settings.shareLocationToChat(itemId, false)
if (shareInfo != null) {
telegramHelper.stopSendingLiveLocationToChat(shareInfo)
- app.settings.lastChatsInfo[shareInfo.chatId] = TelegramSettings.LastChatInfo().apply {
- chatId = shareInfo.chatId
- livePeriod = shareInfo.livePeriod
- }
- log.info("Save chat to last: ${shareInfo.chatId}")
+ settings.addTimePeriodToLastItem(shareInfo.chatId,shareInfo.livePeriod)
}
- removeItem(item)
+ removeItem(item as TdApi.Object)
}
}
}
@@ -802,6 +872,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
(activity as DataSetListener).onDataSetChanged()
}
}
+ } else if (holder is HeaderViewHolder) {
+ holder.header?.text = item as String
}
}
@@ -842,6 +914,10 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
val container: LinearLayout? = view.findViewById(R.id.container)
val time: TextView? = view.findViewById(R.id.time)
}
+
+ inner class HeaderViewHolder(val view: View) : BaseViewHolder(view) {
+ val header: TextView? = view.findViewById(R.id.header)
+ }
}
interface ActionButtonsListener {
@@ -849,4 +925,4 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
}
-class LastChat internal constructor(val chat: TdApi.Chat, val time: Long) : TdApi.Chat()
\ No newline at end of file
+class LastChat internal constructor(val chat: TdApi.Chat, val time: Long)
\ No newline at end of file