This commit is contained in:
Dmitriy Ruban 2019-12-27 19:20:30 +02:00
parent c5cfb47950
commit 11e3da3701
6 changed files with 228 additions and 28 deletions

View 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>

View file

@ -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>

View file

@ -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 &amp; formats</string>

View file

@ -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"
}
}
}

View file

@ -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?,

View file

@ -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
settings.addTimePeriodToLastItem(shareInfo.chatId,shareInfo.livePeriod)
}
log.info("Save chat to last: ${shareInfo.chatId}")
}
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)