From 11e3da3701ba6b70bf63ca418b52c09d000eaaa1 Mon Sep 17 00:00:00 2001 From: Dmitriy Ruban Date: Fri, 27 Dec 2019 19:20:30 +0200 Subject: [PATCH] wip --- .../res/layout/header_list_item.xml | 27 ++++ .../res/layout/last_share_list_item.xml | 23 +++- OsmAnd-telegram/res/values/strings.xml | 1 + .../net/osmand/telegram/TelegramSettings.kt | 76 ++++++++++- .../telegram/helpers/TelegramUiHelper.kt | 7 + .../telegram/ui/MyLocationTabFragment.kt | 122 ++++++++++++++---- 6 files changed, 228 insertions(+), 28 deletions(-) create mode 100644 OsmAnd-telegram/res/layout/header_list_item.xml 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