Add ability to share location to contacts

This commit is contained in:
Chumva 2018-12-05 17:52:26 +02:00
parent 4c2cfb9c97
commit 9b6aa48639
6 changed files with 334 additions and 75 deletions

View file

@ -44,8 +44,8 @@ private val LOC_HISTORY_VALUES_SEC = listOf(
)
private const val SEND_MY_LOC_DEFAULT_INDEX = 6
private const val STALE_LOC_DEFAULT_INDEX = 4
private const val LOC_HISTORY_DEFAULT_INDEX = 2
private const val STALE_LOC_DEFAULT_INDEX = 0
private const val LOC_HISTORY_DEFAULT_INDEX = 7
private const val SETTINGS_NAME = "osmand_telegram_settings"
@ -113,6 +113,15 @@ class TelegramSettings(private val app: TelegramApplication) {
fun isSharingLocationToChat(chatId: Long) = shareChatsInfo.containsKey(chatId)
fun isSharingLocationToUser(userId: Int): Boolean {
shareChatsInfo.forEach { (_, shareInfo: ShareChatInfo) ->
if (shareInfo.userId == userId) {
return true
}
}
return false
}
fun hasAnyChatToShowOnMap() = !hiddenOnMapChats.containsAll(getLiveNowChats())
fun isShowingChatOnMap(chatId: Long) = !hiddenOnMapChats.contains(chatId)
@ -132,35 +141,33 @@ class TelegramSettings(private val app: TelegramApplication) {
addActiveTime: Long = ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0]
) {
if (share) {
val lp: Long = when {
livePeriod < TelegramHelper.MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC -> TelegramHelper.MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC.toLong()
else -> livePeriod
}
var shareChatInfo = shareChatsInfo[chatId]
if (shareChatInfo == null) {
shareChatInfo = ShareChatInfo()
}
val currentTime = System.currentTimeMillis() / 1000
val user = app.telegramHelper.getCurrentUser()
if (user != null && currentSharingMode != user.id.toString() && shareChatInfo.start == -1L) {
shareChatInfo.shouldSendViaBotMessage = true
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)
}
shareChatInfo.chatId = chatId
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
updateChatShareInfo(shareChatInfo, livePeriod, addActiveTime)
shareChatsInfo[chatId] = shareChatInfo
} else {
shareChatsInfo.remove(chatId)
}
}
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()
}
@ -235,10 +242,12 @@ class TelegramSettings(private val app: TelegramApplication) {
fun updateShareInfo(message: TdApi.Message) {
val shareChatInfo = shareChatsInfo[message.chatId]
val content = message.content
if (shareChatInfo != null && content is TdApi.MessageLocation) {
if (shareChatInfo != null) {
shareChatInfo.currentMessageId = message.id
shareChatInfo.lastSuccessfulLocation = LatLon(content.location.latitude, content.location.longitude)
shareChatInfo.lastSuccessfulSendTimeMs = Math.max(message.editDate, message.date) * 1000L
if (content is TdApi.MessageLocation) {
shareChatInfo.lastSuccessfulLocation = LatLon(content.location.latitude, content.location.longitude)
shareChatInfo.lastSuccessfulSendTimeMs = Math.max(message.editDate, message.date) * 1000L
}
}
}
@ -271,6 +280,31 @@ class TelegramSettings(private val app: TelegramApplication) {
}
}
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
}
private fun getNewSharingStatusHistoryItem(): SharingStatus {
return SharingStatus().apply {
statusChangeTime = System.currentTimeMillis()
@ -472,6 +506,7 @@ class TelegramSettings(private val app: TelegramApplication) {
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)
@ -493,6 +528,7 @@ class TelegramSettings(private val app: TelegramApplication) {
val obj = json.getJSONObject(i)
val shareInfo = ShareChatInfo().apply {
chatId = obj.optLong(ShareChatInfo.CHAT_ID_KEY)
userId = obj.optInt(ShareChatInfo.USER_ID_KEY)
start = obj.optLong(ShareChatInfo.START_KEY)
livePeriod = obj.optLong(ShareChatInfo.LIVE_PERIOD_KEY)
currentMessageLimit = obj.optLong(ShareChatInfo.LIMIT_KEY)
@ -738,6 +774,7 @@ class TelegramSettings(private val app: TelegramApplication) {
class ShareChatInfo {
var chatId = -1L
var userId = -1
var start = -1L
var livePeriod = -1L
var currentMessageLimit = -1L
@ -767,6 +804,7 @@ class TelegramSettings(private val app: TelegramApplication) {
companion object {
internal const val CHAT_ID_KEY = "chatId"
internal const val USER_ID_KEY = "userId"
internal const val START_KEY = "start"
internal const val LIVE_PERIOD_KEY = "livePeriod"
internal const val LIMIT_KEY = "limit"

View file

@ -68,6 +68,7 @@ class TelegramHelper private constructor() {
var lastTelegramUpdateTime: Int = 0
private val users = ConcurrentHashMap<Int, TdApi.User>()
private val contacts = ConcurrentHashMap<Int, TdApi.User>()
private val basicGroups = ConcurrentHashMap<Int, TdApi.BasicGroup>()
private val supergroups = ConcurrentHashMap<Int, TdApi.Supergroup>()
private val secretChats = ConcurrentHashMap<Int, TdApi.SecretChat>()
@ -141,6 +142,8 @@ class TelegramHelper private constructor() {
fun getChatListIds() = getChatList().map { it.chatId }
fun getContacts() = contacts
fun getChatIds() = chats.keys().toList()
fun getChat(id: Long) = chats[id]
@ -237,6 +240,7 @@ class TelegramHelper private constructor() {
fun onTelegramChatsRead()
fun onTelegramChatsChanged()
fun onTelegramChatChanged(chat: TdApi.Chat)
fun onTelegramChatCreated(chat: TdApi.Chat)
fun onTelegramUserChanged(user: TdApi.User)
fun onTelegramError(code: Int, message: String)
}
@ -561,6 +565,73 @@ class TelegramHelper private constructor() {
}
}
private fun requestContacts(){
client?.send(TdApi.GetContacts()) { obj ->
when (obj.constructor) {
TdApi.Error.CONSTRUCTOR -> {
val error = obj as TdApi.Error
if (error.code != IGNORED_ERROR_CODE) {
listener?.onTelegramError(error.code, error.message)
}
}
TdApi.Users.CONSTRUCTOR -> {
val usersIds = obj as TdApi.Users
usersIds.userIds.forEach {
requestUser(it)
}
}
}
}
}
private fun requestUser(id: Int) {
client?.send(TdApi.GetUser(id)) { obj ->
when (obj.constructor) {
TdApi.Error.CONSTRUCTOR -> {
val error = obj as TdApi.Error
if (error.code != IGNORED_ERROR_CODE) {
listener?.onTelegramError(error.code, error.message)
}
}
TdApi.User.CONSTRUCTOR -> {
val user = obj as TdApi.User
contacts[user.id] = user
if (!hasLocalUserPhoto(user) && hasRemoteUserPhoto(user)) {
requestUserPhoto(user)
}
}
}
}
}
fun createPrivateChatWithUser(
userId: Int,
shareInfo: TelegramSettings.ShareChatInfo,
shareChatsInfo: ConcurrentHashMap<Long, TelegramSettings.ShareChatInfo>
) {
client?.send(TdApi.CreatePrivateChat(userId, false)) { obj ->
when (obj.constructor) {
TdApi.Error.CONSTRUCTOR -> {
val error = obj as TdApi.Error
needRefreshActiveLiveLocationMessages = true
if (error.code == MESSAGE_CANNOT_BE_EDITED_ERROR_CODE) {
shareInfo.shouldDeletePreviousMessage = true
} else if (error.code != IGNORED_ERROR_CODE) {
shareInfo.hasSharingError = true
outgoingMessagesListeners.forEach {
it.onSendLiveLocationError(error.code, error.message)
}
}
}
TdApi.Chat.CONSTRUCTOR -> {
shareInfo.chatId = (obj as TdApi.Chat).id
shareChatsInfo[shareInfo.chatId] = shareInfo
listener?.onTelegramChatCreated(obj)
}
}
}
}
fun loadMessage(chatId: Long, messageId: Long) {
requestMessage(chatId, messageId, this@TelegramHelper::addNewMessage)
}
@ -896,6 +967,7 @@ class TelegramHelper private constructor() {
if (haveAuthorization) {
requestChats(true)
requestCurrentUser()
requestContacts()
}
}
val newAuthState = getTelegramAuthorizationState()
@ -1085,6 +1157,9 @@ class TelegramHelper private constructor() {
val updateUser = obj as TdApi.UpdateUser
val user = updateUser.user
users[updateUser.user.id] = user
if (user.outgoingLink is TdApi.LinkStateIsContact) {
contacts[user.id] = user
}
if (isOsmAndBot(user.id)) {
osmandBot = user
}

View file

@ -171,6 +171,10 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
updateList()
}
override fun onTelegramChatCreated(chat: TdApi.Chat) {
updateList()
}
override fun onTelegramUserChanged(user: TdApi.User) {
updateList()
}

View file

@ -254,6 +254,12 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
}
}
override fun onTelegramChatCreated(chat: TdApi.Chat) {
runOnUi {
listeners.forEach { it.get()?.onTelegramChatCreated(chat) }
}
}
override fun onTelegramUserChanged(user: TdApi.User) {
val photoPath = telegramHelper.getUserPhotoPath(user)
if (photoPath != null) {

View file

@ -28,6 +28,7 @@ import net.osmand.telegram.utils.OsmandFormatter
import org.drinkless.td.libcore.telegram.TdApi
private const val SELECTED_CHATS_KEY = "selected_chats"
private const val SELECTED_CHATS_USERS = "selected_users"
private const val SHARE_LOCATION_CHAT = 1
private const val DEFAULT_CHAT = 0
@ -71,6 +72,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
private lateinit var appBarOutlineProvider: ViewOutlineProvider
private val selectedChats = HashSet<Long>()
private val selectedUsers = HashSet<Long>()
private var actionButtonsListener: ActionButtonsListener? = null
@ -97,9 +99,8 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
savedInstanceState?.apply {
selectedChats.addAll(getLongArray(SELECTED_CHATS_KEY).toSet())
if (selectedChats.isNotEmpty()) {
actionButtonsListener?.switchButtonsVisibility(true)
}
selectedUsers.addAll(getLongArray(SELECTED_CHATS_USERS).toSet())
actionButtonsListener?.switchButtonsVisibility((selectedUsers.isNotEmpty() || selectedChats.isNotEmpty()))
}
val mainView = inflater.inflate(R.layout.fragment_my_location_tab, container, false)
@ -191,7 +192,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
mainView.findViewById<View>(R.id.stop_all_sharing_row).setOnClickListener {
fragmentManager?.also { fm ->
DisableSharingBottomSheet.showInstance(fm, this, adapter.chats.size)
DisableSharingBottomSheet.showInstance(fm, this, adapter.items.size)
}
}
@ -274,7 +275,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
TelegramHelper.TelegramAuthorizationState.LOGGING_OUT,
TelegramHelper.TelegramAuthorizationState.CLOSED,
TelegramHelper.TelegramAuthorizationState.UNKNOWN -> {
adapter.chats = mutableListOf()
adapter.items = mutableListOf()
}
else -> Unit
}
@ -292,6 +293,11 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
updateContent()
}
override fun onTelegramChatCreated(chat: TdApi.Chat) {
sharingMode = settings.hasAnyChatToShareLocation()
updateContent()
}
override fun onTelegramUserChanged(user: TdApi.User) {
if (user.id == telegramHelper.getCurrentUser()?.id) {
updateCurrentUserPhoto()
@ -303,9 +309,9 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
fun onPrimaryBtnClick() {
if (selectedChats.isNotEmpty()) {
if (selectedChats.isNotEmpty() || selectedUsers.isNotEmpty()) {
val fm = fragmentManager ?: return
SetTimeDialogFragment.showInstance(fm, selectedChats, this)
SetTimeDialogFragment.showInstance(fm, selectedChats, selectedUsers, this)
}
}
@ -351,6 +357,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
private fun clearSelection() {
selectedChats.clear()
selectedUsers.clear()
adapter.notifyDataSetChanged()
actionButtonsListener?.switchButtonsVisibility(false)
}
@ -453,8 +460,9 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
private fun updateList() {
val chats: MutableList<TdApi.Chat> = mutableListOf()
val items: MutableList<TdApi.Object> = mutableListOf()
val currentUser = telegramHelper.getCurrentUser()
val contacts = telegramHelper.getContacts()
val chatList = if (sharingMode) {
settings.getShareLocationChats()
} else {
@ -470,30 +478,56 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
continue
}
}
chats.add(chat)
items.add(chat)
}
}
if (!sharingMode) {
for (user in contacts.values) {
if ((!sharingMode && settings.isSharingLocationToUser(user.id)) || user.id == currentUser?.id) {
continue
}
items.add(user)
}
}
if (sharingMode && settings.hasAnyChatToShareLocation()) {
adapter.chats = sortAdapterItems(chats)
adapter.items = sortAdapterItems(items)
} else {
adapter.chats = chats
adapter.items = items
}
}
private fun sortAdapterItems(list: MutableList<TdApi.Chat>): MutableList<TdApi.Chat> {
list.sortWith(Comparator<TdApi.Chat> { o1, o2 -> o1.title.compareTo(o2.title) })
private fun sortAdapterItems(list: MutableList<TdApi.Object>): MutableList<TdApi.Object> {
list.sortWith(Comparator<TdApi.Object> { o1, o2 ->
val title1 = when (o1) {
is TdApi.Chat -> o1.title
is TdApi.User -> TelegramUiHelper.getUserName(o1)
else -> ""
}
val title2 = when (o2) {
is TdApi.Chat -> o2.title
is TdApi.User -> TelegramUiHelper.getUserName(o2)
else -> ""
}
title1.compareTo(title2)
})
return list
}
inner class MyLocationListAdapter : RecyclerView.Adapter<MyLocationListAdapter.BaseViewHolder>() {
var chats = mutableListOf<TdApi.Chat>()
var items = mutableListOf<TdApi.Object>()
set(value) {
field = value
notifyDataSetChanged()
}
override fun getItemViewType(position: Int): Int {
return if (settings.isSharingLocationToChat(chats[position].id) && sharingMode) {
val item = items[position]
val id = when (item) {
is TdApi.Chat -> item.id
is TdApi.User -> item.id.toLong()
else -> -1
}
return if (settings.isSharingLocationToChat(id) && sharingMode) {
SHARE_LOCATION_CHAT
} else {
DEFAULT_CHAT
@ -518,14 +552,34 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
val chat = chats[position]
val lastItem = position == itemCount - 1
val placeholderId = if (telegramHelper.isGroup(chat)) R.drawable.img_group_picture else R.drawable.img_user_picture
val live = settings.isSharingLocationToChat(chat.id)
val shareInfo = settings.getChatsShareInfo()[chat.id]
val item = items[position]
val isChat = item is TdApi.Chat
val itemId = if (isChat) {
(item as TdApi.Chat).id
} else {
(item as TdApi.User).id.toLong()
}
TelegramUiHelper.setupPhoto(app, holder.icon, chat.photo?.small?.local?.path, placeholderId, false)
holder.title?.text = chat.title
val lastItem = position == itemCount - 1
val placeholderId = if (isChat && telegramHelper.isGroup(item as TdApi.Chat)) R.drawable.img_group_picture else R.drawable.img_user_picture
val live = (isChat && settings.isSharingLocationToChat(itemId))
val shareInfo = if (isChat) settings.getChatsShareInfo()[itemId] else null
val photoPath = when (item) {
is TdApi.Chat -> item.photo?.small?.local?.path
is TdApi.User -> item.profilePhoto?.small?.local?.path
else -> null
}
TelegramUiHelper.setupPhoto(app, holder.icon, photoPath, placeholderId, false)
val title = when (item) {
is TdApi.Chat -> item.title
is TdApi.User -> TelegramUiHelper.getUserName(item)
else -> null
}
holder.title?.text = title
if (holder is ChatViewHolder) {
holder.description?.visibility = View.GONE
@ -535,21 +589,33 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
holder.checkBox?.apply {
visibility = View.VISIBLE
setOnCheckedChangeListener(null)
isChecked = selectedChats.contains(chat.id)
isChecked = if (isChat) {
selectedChats.contains(itemId)
} else {
selectedUsers.contains(itemId)
}
setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
selectedChats.add(chat.id)
if (isChat) {
selectedChats.add(itemId)
} else {
selectedUsers.add(itemId)
}
} else {
selectedChats.remove(chat.id)
if (isChat) {
selectedChats.remove(itemId)
} else {
selectedUsers.remove(itemId)
}
}
actionButtonsListener?.switchButtonsVisibility(selectedChats.isNotEmpty())
actionButtonsListener?.switchButtonsVisibility(selectedChats.isNotEmpty() || selectedUsers.isNotEmpty())
}
}
}
holder.bottomShadow?.visibility = if (lastItem) View.VISIBLE else View.GONE
holder.itemView.setOnClickListener {
if (live) {
settings.shareLocationToChat(chat.id, false)
settings.shareLocationToChat(itemId, false)
shareLocationHelper.stopSharingLocation()
notifyItemChanged(position)
} else {
@ -563,11 +629,11 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
isChecked = live
setOnCheckedChangeListener { _, isChecked ->
if (!isChecked) {
settings.shareLocationToChat(chat.id, false)
settings.shareLocationToChat(itemId, false)
if (shareInfo != null) {
telegramHelper.stopSendingLiveLocationToChat(shareInfo)
}
removeItem(chat)
removeItem(item)
}
}
}
@ -591,7 +657,11 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
val expireTime = shareInfo?.getChatLiveMessageExpireTime() ?: 0
val newLivePeriod = expireTime + (shareInfo?.additionalActiveTime ?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0])
val nextAdditionalActiveTime = shareInfo?.getNextAdditionalActiveTime() ?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[1]
settings.shareLocationToChat(chat.id, true, newLivePeriod, nextAdditionalActiveTime)
if (isChat) {
settings.shareLocationToChat(itemId, true, newLivePeriod, nextAdditionalActiveTime)
} else {
settings.shareLocationToUser(itemId.toInt(), newLivePeriod, nextAdditionalActiveTime)
}
notifyItemChanged(position)
}
}
@ -616,9 +686,9 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
private fun getStopSharingVisibility(expiresIn: Long) = if (expiresIn > 0) View.VISIBLE else View.INVISIBLE
private fun removeItem(chat: TdApi.Chat) {
chats.remove(chat)
if (chats.isEmpty()) {
private fun removeItem(chat: TdApi.Object) {
items.remove(chat)
if (items.isEmpty()) {
sharingMode = false
updateContent()
shareLocationHelper.stopSharingLocation()
@ -627,7 +697,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
}
override fun getItemCount() = chats.size
override fun getItemCount() = items.size
abstract inner class BaseViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val icon: ImageView? = view.findViewById(R.id.icon)

View file

@ -14,8 +14,8 @@ import android.widget.TextView
import net.osmand.Location
import net.osmand.data.LatLon
import net.osmand.telegram.R
import net.osmand.telegram.TelegramLocationProvider.TelegramLocationListener
import net.osmand.telegram.TelegramLocationProvider.TelegramCompassListener
import net.osmand.telegram.TelegramLocationProvider.TelegramLocationListener
import net.osmand.telegram.helpers.ShareLocationHelper
import net.osmand.telegram.helpers.TelegramUiHelper
import net.osmand.telegram.ui.SetTimeDialogFragment.SetTimeListAdapter.ChatViewHolder
@ -36,6 +36,7 @@ class SetTimeDialogFragment : BaseDialogFragment(), TelegramLocationListener, Te
private lateinit var timeForAllValue: TextView
private val chatLivePeriods = HashMap<Long, Long>()
private val userLivePeriods = HashMap<Long, Long>()
private var location: Location? = null
private var heading: Float? = null
@ -90,6 +91,9 @@ class SetTimeDialogFragment : BaseDialogFragment(), TelegramLocationListener, Te
chatLivePeriods.forEach { (chatId, livePeriod) ->
settings.shareLocationToChat(chatId, true, livePeriod)
}
userLivePeriods.forEach { (userId, livePeriod) ->
settings.shareLocationToUser(userId.toInt(), livePeriod)
}
app.shareLocationHelper.startSharingLocation()
targetFragment?.also {
it.onActivityResult(targetRequestCode, LOCATION_SHARED_REQUEST_CODE, null)
@ -121,7 +125,13 @@ class SetTimeDialogFragment : BaseDialogFragment(), TelegramLocationListener, Te
chats.add(id)
chats.add(livePeriod)
}
val users = mutableListOf<Long>()
for ((id, livePeriod) in userLivePeriods) {
users.add(id)
users.add(livePeriod)
}
outState.putLongArray(CHATS_KEY, chats.toLongArray())
outState.putLongArray(USERS_KEY, users.toLongArray())
}
override fun updateLocation(location: Location?) {
@ -167,17 +177,27 @@ class SetTimeDialogFragment : BaseDialogFragment(), TelegramLocationListener, Te
private fun readFromBundle(bundle: Bundle?) {
chatLivePeriods.clear()
userLivePeriods.clear()
bundle?.getLongArray(CHATS_KEY)?.also {
for (i in 0 until it.size step 2) {
val livePeriod = settings.getChatLivePeriod(it[i])
chatLivePeriods[it[i]] = livePeriod ?: it[i + 1]
}
}
bundle?.getLongArray(USERS_KEY)?.also {
for (j in 0 until it.size step 2) {
val livePeriod = settings.getChatLivePeriod(it[j])
userLivePeriods[it[j]] = livePeriod ?: it[j + 1]
}
}
}
private fun getTimeForAll(useDefValue: Boolean = false): Long {
val returnVal = if (useDefValue) DEFAULT_VISIBLE_TIME_SECONDS else NO_VALUE
val iterator = chatLivePeriods.values.iterator()
val allTime = mutableListOf<Long>()
allTime.addAll(chatLivePeriods.values)
allTime.addAll(userLivePeriods.values)
val iterator = allTime.iterator()
if (!iterator.hasNext()) {
return returnVal
}
@ -202,7 +222,7 @@ class SetTimeDialogFragment : BaseDialogFragment(), TelegramLocationListener, Te
}
}
private fun selectDuration(id: Long? = null) {
private fun selectDuration(id: Long? = null, isChat: Boolean = true) {
val timeForAll = getTimeForAll(true)
val defSeconds = if (id == null) timeForAll else chatLivePeriods[id] ?: timeForAll
val (defHours, defMinutes) = secondsToHoursAndMinutes(defSeconds)
@ -213,11 +233,18 @@ class SetTimeDialogFragment : BaseDialogFragment(), TelegramLocationListener, Te
TimeUnit.MINUTES.toSeconds(minutes.toLong())
if (seconds >= ShareLocationHelper.MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC) {
if (id != null) {
chatLivePeriods[id] = seconds
if (isChat) {
chatLivePeriods[id] = seconds
} else {
userLivePeriods[id] = seconds
}
} else {
chatLivePeriods.keys.forEach {
chatLivePeriods[it] = seconds
}
userLivePeriods.keys.forEach {
userLivePeriods[it] = seconds
}
}
updateTimeForAllRow()
adapter.notifyDataSetChanged()
@ -242,17 +269,19 @@ class SetTimeDialogFragment : BaseDialogFragment(), TelegramLocationListener, Te
}
private fun updateList() {
val chats: MutableList<TdApi.Chat> = mutableListOf()
val items: MutableList<TdApi.Object> = mutableListOf()
telegramHelper.getChatList().filter { chatLivePeriods.keys.contains(it.chatId) }
.forEach { orderedChat ->
telegramHelper.getChat(orderedChat.chatId)?.also { chats.add(it) }
telegramHelper.getChat(orderedChat.chatId)?.also { items.add(it) }
}
adapter.chats = chats
telegramHelper.getContacts().values.filter { userLivePeriods.keys.contains(it.id.toLong()) }
.forEach { user -> items.add(user) }
adapter.items = items
}
inner class SetTimeListAdapter : RecyclerView.Adapter<ChatViewHolder>() {
var chats: List<TdApi.Chat> = emptyList()
var items: List<TdApi.Object> = emptyList()
set(value) {
field = value
notifyDataSetChanged()
@ -265,18 +294,38 @@ class SetTimeDialogFragment : BaseDialogFragment(), TelegramLocationListener, Te
}
override fun onBindViewHolder(holder: ChatViewHolder, position: Int) {
val chat = chats[position]
val placeholderId = if (telegramHelper.isGroup(chat)) R.drawable.img_group_picture else R.drawable.img_user_picture
val item = items[position]
val isChat = item is TdApi.Chat
val itemId = if (isChat) {
(item as TdApi.Chat).id
} else {
(item as TdApi.User).id.toLong()
}
TelegramUiHelper.setupPhoto(app, holder.icon, chat.photo?.small?.local?.path, placeholderId, false)
holder.title?.text = chat.title
val placeholderId = if (isChat && telegramHelper.isGroup((item as TdApi.Chat))) R.drawable.img_group_picture else R.drawable.img_user_picture
if (telegramHelper.isGroup(chat)) {
val photoPath = when (item) {
is TdApi.Chat -> item.photo?.small?.local?.path
is TdApi.User -> item.profilePhoto?.small?.local?.path
else -> null
}
TelegramUiHelper.setupPhoto(app, holder.icon, photoPath, placeholderId, false)
val title = when (item) {
is TdApi.Chat -> item.title
is TdApi.User -> TelegramUiHelper.getUserName(item)
else -> null
}
holder.title?.text = title
if (isChat && telegramHelper.isGroup((item as TdApi.Chat))) {
holder.locationViewContainer?.visibility = View.GONE
holder.description?.visibility = View.VISIBLE
holder.description?.text = getString(R.string.shared_string_group)
} else {
val message = telegramHelper.getChatMessages(chat.id).firstOrNull()
val message = telegramHelper.getChatMessages(itemId).firstOrNull()
val content = message?.content
if (message != null && content is TdApi.MessageLocation && (location != null && content.location != null)) {
val lastUpdated = telegramHelper.getLastUpdatedTime(message)
@ -301,15 +350,19 @@ class SetTimeDialogFragment : BaseDialogFragment(), TelegramLocationListener, Te
holder.textInArea?.apply {
visibility = View.VISIBLE
chatLivePeriods[chat.id]?.also { text = formatLivePeriod(it) }
if (isChat) {
chatLivePeriods[itemId]?.also { text = formatLivePeriod(it) }
} else {
userLivePeriods[itemId]?.also { text = formatLivePeriod(it) }
}
}
holder.bottomShadow?.visibility = View.GONE
holder.itemView.setOnClickListener {
selectDuration(chat.id)
selectDuration(itemId, isChat)
}
}
override fun getItemCount() = chats.size
override fun getItemCount() = items.size
inner class ChatViewHolder(val view: View) : RecyclerView.ViewHolder(view) {
val icon: ImageView? = view.findViewById(R.id.icon)
@ -329,18 +382,31 @@ class SetTimeDialogFragment : BaseDialogFragment(), TelegramLocationListener, Te
private const val TAG = "SetTimeDialogFragment"
private const val CHATS_KEY = "chats_key"
private const val USERS_KEY = "users_key"
private const val DEFAULT_VISIBLE_TIME_SECONDS = 60 * 60L // 1 hour
private const val NO_VALUE = -1L
fun showInstance(fm: FragmentManager, chatIds: Set<Long>, target: Fragment): Boolean {
fun showInstance(fm: FragmentManager, chatIds: Set<Long>, usersIds: Set<Long>, target: Fragment): Boolean {
return try {
val chats = mutableListOf<Long>()
for (id in chatIds) {
chats.add(id)
chats.add(DEFAULT_VISIBLE_TIME_SECONDS)
}
val users = mutableListOf<Long>()
for (id in usersIds) {
users.add(id)
users.add(DEFAULT_VISIBLE_TIME_SECONDS)
}
SetTimeDialogFragment().apply {
arguments = Bundle().apply { putLongArray(CHATS_KEY, chats.toLongArray()) }
arguments = Bundle().apply {
if (chats.isNotEmpty()) {
putLongArray(CHATS_KEY, chats.toLongArray())
}
if (users.isNotEmpty()) {
putLongArray(USERS_KEY, users.toLongArray())
}
}
setTargetFragment(target, LOCATION_SHARED_REQUEST_CODE)
show(fm, TAG)
}