wip
This commit is contained in:
parent
c5cfb47950
commit
11e3da3701
6 changed files with 228 additions and 28 deletions
27
OsmAnd-telegram/res/layout/header_list_item.xml
Normal file
27
OsmAnd-telegram/res/layout/header_list_item.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="25dp" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="54dp"
|
||||
android:background="?attr/shared_chat_card_bg"
|
||||
android:gravity="start|center_vertical"
|
||||
android:paddingStart="@dimen/content_padding_standard"
|
||||
android:paddingLeft="@dimen/content_padding_half"
|
||||
android:paddingRight="@dimen/content_padding_half"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/hint_text_size"
|
||||
app:typeface="@string/font_roboto_mono_bold"
|
||||
tools:text="Suggested" />
|
||||
|
||||
</LinearLayout>
|
|
@ -26,8 +26,11 @@
|
|||
tools:src="@drawable/img_user_picture" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
|
@ -47,13 +50,29 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?attr/android:textColorSecondary"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size"
|
||||
app:typeface="@string/font_roboto_regular"
|
||||
tools:text="for 1 hour" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/start"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_marginEnd="@dimen/image_button_padding"
|
||||
android:layout_marginRight="@dimen/image_button_padding"
|
||||
android:background="?attr/secondary_btn_bg"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="@dimen/image_button_padding"
|
||||
android:paddingRight="@dimen/image_button_padding"
|
||||
android:text="@string/shared_string_start"
|
||||
android:textColor="?attr/ctrl_active_color"
|
||||
android:textSize="@dimen/text_button_text_size"
|
||||
app:typeface="@string/font_roboto_medium"
|
||||
tools:text="Start" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="shared_string_suggested">Suggested</string>
|
||||
<string name="time_zone_descr">Select time zone to show in your location messages.</string>
|
||||
<string name="time_zone">Time zone</string>
|
||||
<string name="units_and_formats">Units & formats</string>
|
||||
|
|
|
@ -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<Long>): 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<Long>()
|
||||
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<Long>().apply {
|
||||
addFirst(time)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun addTimeToPeriods(periods: LinkedList<Long>?, time: Long): LinkedList<Long> {
|
||||
if (periods?.isNotEmpty() != null) {
|
||||
return if (periods.count() < 5) {
|
||||
periods.addFirst(time)
|
||||
periods
|
||||
} else {
|
||||
periods.removeLast()
|
||||
periods.addFirst(time)
|
||||
periods
|
||||
}
|
||||
}
|
||||
return LinkedList<Long>().apply { addFirst(time) }
|
||||
}
|
||||
|
||||
private fun calcLivePeriod(periods: LinkedList<Long>): 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<Long>()
|
||||
|
||||
companion object {
|
||||
internal const val CHAT_ID_KEY = "chatId"
|
||||
internal const val LIVE_PERIOD_KEY = "livePeriod"
|
||||
internal const val PERIODS_KEY = "periods"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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?,
|
||||
|
|
|
@ -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<View>(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<TdApi.Object> = mutableListOf()
|
||||
val lastItems = getLastShareItems()
|
||||
val items: MutableList<Any> = mutableListOf()
|
||||
val chats: MutableList<TdApi.Chat> = 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<TdApi.Object>)
|
||||
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<TdApi.Object>): MutableList<TdApi.Object> {
|
||||
val lastItems: MutableList<TdApi.Object> = 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<LastChat> {
|
||||
val lastItems: MutableList<LastChat> = 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<TdApi.Object>): MutableList<TdApi.Object> {
|
||||
private fun sortAdapterItems(list: MutableList<TdApi.Object>): MutableList<Any> {
|
||||
list.sortWith(Comparator<TdApi.Object> { 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<MyLocationListAdapter.BaseViewHolder>() {
|
||||
var items = mutableListOf<TdApi.Object>()
|
||||
var items = mutableListOf<Any>()
|
||||
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()
|
||||
class LastChat internal constructor(val chat: TdApi.Chat, val time: Long)
|
Loading…
Reference in a new issue