Merge pull request #5667 from osmandapp/AddChatIdsToDuration

Add chat ids to duration in settings
This commit is contained in:
Alexander Sytnyk 2018-07-13 17:13:21 +03:00 committed by GitHub
commit af7c9bed4b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 72 additions and 40 deletions

View file

@ -1,6 +1,7 @@
package net.osmand.telegram package net.osmand.telegram
import android.content.Context import android.content.Context
import net.osmand.telegram.helpers.TelegramHelper
import net.osmand.telegram.utils.OsmandFormatter.MetricsConstants import net.osmand.telegram.utils.OsmandFormatter.MetricsConstants
import net.osmand.telegram.utils.OsmandFormatter.SpeedConstants import net.osmand.telegram.utils.OsmandFormatter.SpeedConstants
@ -18,10 +19,14 @@ private const val SEND_MY_LOCATION_INTERVAL_DEFAULT = 5L * 1000 // 5 seconds
private const val USER_LOCATION_EXPIRE_TIME_KEY = "user_location_expire_time" private const val USER_LOCATION_EXPIRE_TIME_KEY = "user_location_expire_time"
private const val USER_LOCATION_EXPIRE_TIME_DEFAULT = 15L * 60 * 1000 // 15 minutes private const val USER_LOCATION_EXPIRE_TIME_DEFAULT = 15L * 60 * 1000 // 15 minutes
private const val DEFAULT_VISIBLE_TIME_SECONDS = 60 * 60L // 1 hour
private const val TITLES_REPLACED_WITH_IDS = "changed_to_chat_id" private const val TITLES_REPLACED_WITH_IDS = "changed_to_chat_id"
class TelegramSettings(private val app: TelegramApplication) { class TelegramSettings(private val app: TelegramApplication) {
var chatLivePeriods = mutableMapOf<Long, Long>()
private var shareLocationChats: Set<Long> = emptySet() private var shareLocationChats: Set<Long> = emptySet()
private var showOnMapChats: Set<Long> = emptySet() private var showOnMapChats: Set<Long> = emptySet()
@ -52,20 +57,34 @@ class TelegramSettings(private val app: TelegramApplication) {
val showOnMapChats = showOnMapChats.toMutableList() val showOnMapChats = showOnMapChats.toMutableList()
showOnMapChats.intersect(presentChatIds) showOnMapChats.intersect(presentChatIds)
this.showOnMapChats = showOnMapChats.toHashSet() this.showOnMapChats = showOnMapChats.toHashSet()
chatLivePeriods = chatLivePeriods.filter { (key, _) ->
presentChatIds.contains(key)
}.toMutableMap()
} }
fun shareLocationToChat(chatId: Long, share: Boolean) { fun shareLocationToChat(chatId: Long, share: Boolean, livePeriod: Long = DEFAULT_VISIBLE_TIME_SECONDS) {
val shareLocationChats = shareLocationChats.toMutableList() val shareLocationChats = shareLocationChats.toMutableList()
if (share) { if (share) {
val lp: Long = when {
livePeriod < TelegramHelper.MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC -> TelegramHelper.MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC.toLong()
livePeriod > TelegramHelper.MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC -> TelegramHelper.MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC.toLong()
else -> livePeriod
}
chatLivePeriods[chatId] = lp
shareLocationChats.add(chatId) shareLocationChats.add(chatId)
} else { } else {
shareLocationChats.remove(chatId) shareLocationChats.remove(chatId)
chatLivePeriods.remove(chatId)
} }
this.shareLocationChats = shareLocationChats.toHashSet() this.shareLocationChats = shareLocationChats.toHashSet()
} }
fun getChatLivePeriod(chatId: Long) = chatLivePeriods[chatId]
fun stopSharingLocationToChats() { fun stopSharingLocationToChats() {
this.shareLocationChats = emptySet() this.shareLocationChats = emptySet()
this.chatLivePeriods.clear()
} }
fun showChatOnMap(chatId: Long, show: Boolean) { fun showChatOnMap(chatId: Long, show: Boolean) {

View file

@ -38,9 +38,9 @@ class ShareLocationHelper(private val app: TelegramApplication) {
lastLocation = location lastLocation = location
if (location != null && app.isInternetConnectionAvailable) { if (location != null && app.isInternetConnectionAvailable) {
val shareLocationChats = app.settings.getShareLocationChats() val chatLivePeriods = app.settings.chatLivePeriods
if (shareLocationChats.isNotEmpty()) { if (chatLivePeriods.isNotEmpty()) {
app.telegramHelper.sendLiveLocationMessage(shareLocationChats, MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC, location.latitude, location.longitude) app.telegramHelper.sendLiveLocationMessage(chatLivePeriods, location.latitude, location.longitude)
} }
lastLocationMessageSentTime = System.currentTimeMillis() lastLocationMessageSentTime = System.currentTimeMillis()
} }

View file

@ -385,15 +385,15 @@ class TelegramHelper private constructor() {
* @latitude Latitude of the location * @latitude Latitude of the location
* @longitude Longitude of the location * @longitude Longitude of the location
*/ */
fun sendLiveLocationMessage(chatIds: List<Long>, livePeriod: Int, latitude: Double, longitude: Double): Boolean { fun sendLiveLocationMessage(chatLivePeriods: Map<Long, Long>, latitude: Double, longitude: Double): Boolean {
if (!requestingActiveLiveLocationMessages && haveAuthorization) { if (!requestingActiveLiveLocationMessages && haveAuthorization) {
if (needRefreshActiveLiveLocationMessages) { if (needRefreshActiveLiveLocationMessages) {
getActiveLiveLocationMessages { getActiveLiveLocationMessages {
sendLiveLocationImpl(chatIds, livePeriod, latitude, longitude) sendLiveLocationImpl(chatLivePeriods, latitude, longitude)
} }
needRefreshActiveLiveLocationMessages = false needRefreshActiveLiveLocationMessages = false
} else { } else {
sendLiveLocationImpl(chatIds, livePeriod, latitude, longitude) sendLiveLocationImpl(chatLivePeriods, latitude, longitude)
} }
return true return true
} }
@ -428,24 +428,24 @@ class TelegramHelper private constructor() {
} }
} }
private fun sendLiveLocationImpl(chatIds: List<Long>, livePeriod: Int, latitude: Double, longitude: Double) { private fun sendLiveLocationImpl(chatLivePeriods: Map<Long, Long>, latitude: Double, longitude: Double) {
val lp = when {
livePeriod < MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC -> MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC
livePeriod > MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC -> MAX_LOCATION_MESSAGE_LIVE_PERIOD_SEC
else -> livePeriod
}
val location = TdApi.Location(latitude, longitude) val location = TdApi.Location(latitude, longitude)
val content = TdApi.InputMessageLocation(location, lp) chatLivePeriods.forEach { chatId, livePeriod ->
val content = TdApi.InputMessageLocation(location, livePeriod.toInt())
for (chatId in chatIds) {
val msgId = chatLiveMessages[chatId] val msgId = chatLiveMessages[chatId]
if (msgId != null) { if (msgId != null) {
if (msgId != 0L) { if (msgId != 0L) {
client?.send(TdApi.EditMessageLiveLocation(chatId, msgId, null, location), liveLocationMessageUpdatesHandler) client?.send(
TdApi.EditMessageLiveLocation(chatId, msgId, null, location),
liveLocationMessageUpdatesHandler
)
} }
} else { } else {
chatLiveMessages[chatId] = 0L chatLiveMessages[chatId] = 0L
client?.send(TdApi.SendMessage(chatId, 0, false, true, null, content), liveLocationMessageUpdatesHandler) client?.send(
TdApi.SendMessage(chatId, 0, false, true, null, content),
liveLocationMessageUpdatesHandler
)
} }
} }
} }

View file

@ -159,7 +159,7 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
if (AndroidUtils.isLocationPermissionAvailable(this)) { if (AndroidUtils.isLocationPermissionAvailable(this)) {
app.locationProvider.resumeAllUpdates() app.locationProvider.resumeAllUpdates()
} else { } else {
requestLocationPermission() AndroidUtils.requestLocationPermission(this)
} }
if (settings.hasAnyChatToShowOnMap() && osmandAidlHelper.isOsmandNotInstalled()) { if (settings.hasAnyChatToShowOnMap() && osmandAidlHelper.isOsmandNotInstalled()) {
showOsmandMissingDialog() showOsmandMissingDialog()
@ -373,10 +373,6 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
} }
} }
private fun requestLocationPermission() {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), PERMISSION_REQUEST_LOCATION)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults) super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (grantResults.isEmpty()) { if (grantResults.isEmpty()) {
@ -475,7 +471,7 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
if (settings.hasAnyChatToShareLocation()) { if (settings.hasAnyChatToShareLocation()) {
if (!AndroidUtils.isLocationPermissionAvailable(view.context)) { if (!AndroidUtils.isLocationPermissionAvailable(view.context)) {
if (isChecked) { if (isChecked) {
requestLocationPermission() AndroidUtils.requestLocationPermission(this@MainActivity)
} }
} else { } else {
app.shareLocationHelper.startSharingLocation() app.shareLocationHelper.startSharingLocation()

View file

@ -11,12 +11,12 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import android.widget.Toast
import net.osmand.telegram.R import net.osmand.telegram.R
import net.osmand.telegram.TelegramApplication import net.osmand.telegram.TelegramApplication
import net.osmand.telegram.helpers.ShareLocationHelper import net.osmand.telegram.helpers.ShareLocationHelper
import net.osmand.telegram.helpers.TelegramUiHelper import net.osmand.telegram.helpers.TelegramUiHelper
import net.osmand.telegram.ui.SetTimeDialogFragment.SetTimeListAdapter.ChatViewHolder import net.osmand.telegram.ui.SetTimeDialogFragment.SetTimeListAdapter.ChatViewHolder
import net.osmand.telegram.utils.AndroidUtils
import org.drinkless.td.libcore.telegram.TdApi import org.drinkless.td.libcore.telegram.TdApi
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -26,13 +26,14 @@ class SetTimeDialogFragment : DialogFragment() {
get() = activity?.application as TelegramApplication get() = activity?.application as TelegramApplication
private val telegramHelper get() = app.telegramHelper private val telegramHelper get() = app.telegramHelper
private val settings get() = app.settings
private val adapter = SetTimeListAdapter() private val adapter = SetTimeListAdapter()
private lateinit var timeForAllTitle: TextView private lateinit var timeForAllTitle: TextView
private lateinit var timeForAllValue: TextView private lateinit var timeForAllValue: TextView
private val chatIdsToDuration = HashMap<Long, Long>() private val chatLivePeriods = HashMap<Long, Long>()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -76,7 +77,15 @@ class SetTimeDialogFragment : DialogFragment() {
view.findViewById<TextView>(R.id.primary_btn).apply { view.findViewById<TextView>(R.id.primary_btn).apply {
text = getString(R.string.shared_string_share) text = getString(R.string.shared_string_share)
setOnClickListener { setOnClickListener {
Toast.makeText(context, "Share", Toast.LENGTH_SHORT).show() if (!AndroidUtils.isLocationPermissionAvailable(view.context)) {
AndroidUtils.requestLocationPermission(activity!!)
} else {
chatLivePeriods.forEach { chatId, livePeriod ->
settings.shareLocationToChat(chatId, true, livePeriod)
}
app.shareLocationHelper.startSharingLocation()
dismiss()
}
} }
} }
@ -91,25 +100,26 @@ class SetTimeDialogFragment : DialogFragment() {
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
val chats = mutableListOf<Long>() val chats = mutableListOf<Long>()
for ((id, duration) in chatIdsToDuration) { for ((id, livePeriod) in chatLivePeriods) {
chats.add(id) chats.add(id)
chats.add(duration) chats.add(livePeriod)
} }
outState.putLongArray(CHATS_KEY, chats.toLongArray()) outState.putLongArray(CHATS_KEY, chats.toLongArray())
} }
private fun readFromBundle(bundle: Bundle?) { private fun readFromBundle(bundle: Bundle?) {
chatIdsToDuration.clear() chatLivePeriods.clear()
bundle?.getLongArray(CHATS_KEY)?.also { bundle?.getLongArray(CHATS_KEY)?.also {
for (i in 0 until it.size step 2) { for (i in 0 until it.size step 2) {
chatIdsToDuration[it[i]] = it[i + 1] val livePeriod = settings.getChatLivePeriod(it[i])
chatLivePeriods[it[i]] = livePeriod ?: it[i + 1]
} }
} }
} }
private fun getTimeForAll(useDefValue: Boolean = false): Long { private fun getTimeForAll(useDefValue: Boolean = false): Long {
val returnVal = if (useDefValue) DEFAULT_VISIBLE_TIME_SECONDS else NO_VALUE val returnVal = if (useDefValue) DEFAULT_VISIBLE_TIME_SECONDS else NO_VALUE
val iterator = chatIdsToDuration.values.iterator() val iterator = chatLivePeriods.values.iterator()
if (!iterator.hasNext()) { if (!iterator.hasNext()) {
return returnVal return returnVal
} }
@ -127,7 +137,7 @@ class SetTimeDialogFragment : DialogFragment() {
if (timeForAll != NO_VALUE) { if (timeForAll != NO_VALUE) {
timeForAllTitle.text = getString(R.string.visible_time_for_all) timeForAllTitle.text = getString(R.string.visible_time_for_all)
timeForAllValue.visibility = View.VISIBLE timeForAllValue.visibility = View.VISIBLE
timeForAllValue.text = formatDuration(timeForAll) timeForAllValue.text = formatLivePeriod(timeForAll)
} else { } else {
timeForAllTitle.text = getString(R.string.set_visible_time_for_all) timeForAllTitle.text = getString(R.string.set_visible_time_for_all)
timeForAllValue.visibility = View.GONE timeForAllValue.visibility = View.GONE
@ -136,7 +146,7 @@ class SetTimeDialogFragment : DialogFragment() {
private fun selectDuration(id: Long? = null) { private fun selectDuration(id: Long? = null) {
val timeForAll = getTimeForAll(true) val timeForAll = getTimeForAll(true)
val defSeconds = if (id == null) timeForAll else chatIdsToDuration[id] ?: timeForAll val defSeconds = if (id == null) timeForAll else chatLivePeriods[id] ?: timeForAll
val (defHours, defMinutes) = secondsToHoursAndMinutes(defSeconds) val (defHours, defMinutes) = secondsToHoursAndMinutes(defSeconds)
TimePickerDialog( TimePickerDialog(
context, context,
@ -145,10 +155,10 @@ class SetTimeDialogFragment : DialogFragment() {
TimeUnit.MINUTES.toSeconds(minutes.toLong()) TimeUnit.MINUTES.toSeconds(minutes.toLong())
if (seconds >= ShareLocationHelper.MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC) { if (seconds >= ShareLocationHelper.MIN_LOCATION_MESSAGE_LIVE_PERIOD_SEC) {
if (id != null) { if (id != null) {
chatIdsToDuration[id] = seconds chatLivePeriods[id] = seconds
} else { } else {
chatIdsToDuration.keys.forEach { chatLivePeriods.keys.forEach {
chatIdsToDuration[it] = seconds chatLivePeriods[it] = seconds
} }
} }
updateTimeForAllRow() updateTimeForAllRow()
@ -164,7 +174,7 @@ class SetTimeDialogFragment : DialogFragment() {
return Pair(hours.toInt(), minutes.toInt()) return Pair(hours.toInt(), minutes.toInt())
} }
private fun formatDuration(seconds: Long): String { private fun formatLivePeriod(seconds: Long): String {
val (hours, minutes) = secondsToHoursAndMinutes(seconds) val (hours, minutes) = secondsToHoursAndMinutes(seconds)
return when { return when {
hours != 0 && minutes == 0 -> getString(R.string.hours_format, hours) hours != 0 && minutes == 0 -> getString(R.string.hours_format, hours)
@ -175,7 +185,7 @@ class SetTimeDialogFragment : DialogFragment() {
private fun updateList() { private fun updateList() {
val chats: MutableList<TdApi.Chat> = mutableListOf() val chats: MutableList<TdApi.Chat> = mutableListOf()
telegramHelper.getChatList().filter { chatIdsToDuration.keys.contains(it.chatId) } telegramHelper.getChatList().filter { chatLivePeriods.keys.contains(it.chatId) }
.forEach { orderedChat -> .forEach { orderedChat ->
telegramHelper.getChat(orderedChat.chatId)?.also { chats.add(it) } telegramHelper.getChat(orderedChat.chatId)?.also { chats.add(it) }
} }
@ -204,7 +214,7 @@ class SetTimeDialogFragment : DialogFragment() {
holder.description?.text = "Some description" // FIXME holder.description?.text = "Some description" // FIXME
holder.textInArea?.apply { holder.textInArea?.apply {
visibility = View.VISIBLE visibility = View.VISIBLE
chatIdsToDuration[chat.id]?.also { text = formatDuration(it) } chatLivePeriods[chat.id]?.also { text = formatLivePeriod(it) }
} }
holder.bottomShadow?.visibility = View.GONE holder.bottomShadow?.visibility = View.GONE
holder.itemView.setOnClickListener { holder.itemView.setOnClickListener {

View file

@ -19,6 +19,8 @@ import android.view.inputmethod.InputMethodManager
import java.io.File import java.io.File
object AndroidUtils { object AndroidUtils {
private const val PERMISSION_REQUEST_LOCATION = 1
private fun isHardwareKeyboardAvailable(context: Context): Boolean { private fun isHardwareKeyboardAvailable(context: Context): Boolean {
return context.resources.configuration.keyboard != Configuration.KEYBOARD_NOKEYS return context.resources.configuration.keyboard != Configuration.KEYBOARD_NOKEYS
@ -50,6 +52,11 @@ object AndroidUtils {
return ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED return ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
} }
fun requestLocationPermission(activity: Activity) {
ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), PERMISSION_REQUEST_LOCATION)
}
fun dpToPx(ctx: Context, dp: Float): Int { fun dpToPx(ctx: Context, dp: Float): Int {
val r = ctx.resources val r = ctx.resources
return TypedValue.applyDimension( return TypedValue.applyDimension(