Telegram sharing status init

This commit is contained in:
Chumva 2018-10-12 19:17:38 +03:00
parent 519827262c
commit 0ff05fd0a6
15 changed files with 595 additions and 74 deletions

View file

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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"
tools:layout_gravity="bottom">
<android.support.design.widget.CoordinatorLayout
android:id="@+id/scroll_view_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/list_view_bottom_padding">
<android.support.v4.widget.NestedScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:behavior_hideable="true"
app:behavior_peekHeight="@dimen/bottom_sheet_peek_height"
app:layout_behavior="@string/bottom_sheet_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/card_bg_color"
android:orientation="vertical">
<net.osmand.telegram.ui.views.TextViewEx
android:layout_width="match_parent"
android:layout_height="48dp"
android:paddingLeft="@dimen/content_padding_standard"
android:paddingRight="@dimen/content_padding_standard"
android:text="@string/sharing_status"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/list_item_title_text_size"
app:firstBaselineToTopHeight="28sp"
app:typeface="@string/font_roboto_medium"/>
<LinearLayout
android:id="@+id/items_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:background="?attr/card_bg_color">
<include
layout="@layout/secondary_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/content_padding_half"/>
</FrameLayout>
</FrameLayout>

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
<android.support.design.widget.CoordinatorLayout 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"
@ -16,6 +15,7 @@
android:id="@+id/image_container"
android:layout_width="match_parent"
android:layout_height="@dimen/my_location_image_height"
android:visibility="gone"
app:layout_scrollFlags="scroll">
<ImageView
@ -50,11 +50,12 @@
android:id="@+id/text_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/content_padding_standard"
android:animateLayoutChanges="true"
android:orientation="vertical"
android:paddingLeft="@dimen/my_location_text_sides_margin"
android:layout_marginBottom="@dimen/content_padding_standard"
android:paddingRight="@dimen/my_location_text_sides_margin">
android:paddingRight="@dimen/my_location_text_sides_margin"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
@ -157,6 +158,7 @@
android:gravity="center_vertical">
<net.osmand.telegram.ui.views.TextViewEx
android:id="@+id/status_title"
android:layout_width="0dp"
android:layout_height="@dimen/action_bar_height"
android:layout_weight="1"
@ -166,23 +168,21 @@
android:maxLines="1"
android:paddingLeft="@dimen/content_padding_standard"
android:paddingRight="@dimen/content_padding_standard"
android:text="@string/my_location"
android:textColor="@color/app_bar_title_light"
android:textSize="@dimen/title_text_size"
app:typeface="@string/font_roboto_mono_bold" />
app:typeface="@string/font_roboto_mono_bold"
tools:text="@string/sharing_enabled"/>
<ImageView
android:id="@+id/options_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="@dimen/content_padding_standard"
android:layout_marginRight="@dimen/content_padding_standard"
android:background="?attr/selectableItemBackgroundBorderless"
android:paddingLeft="@dimen/content_padding_half"
android:paddingRight="@dimen/content_padding_half"
android:paddingLeft="@dimen/content_padding_standard"
android:paddingRight="@dimen/content_padding_standard"
tools:src="@drawable/ic_action_other_menu"
tools:tint="@color/icon_light"
tools:visibility="visible" />
tools:visibility="visible"/>
</LinearLayout>
@ -192,38 +192,106 @@
android:layout_height="1dp"
android:layout_marginLeft="@dimen/content_padding_standard"
android:layout_marginStart="@dimen/content_padding_standard"
android:background="?attr/card_divider_color" />
android:background="?attr/card_divider_color"/>
<LinearLayout
android:id="@+id/stop_all_sharing_row"
android:layout_width="match_parent"
android:layout_height="@dimen/action_bar_height"
android:background="?attr/selectableItemBackground"
android:gravity="center_vertical"
android:paddingLeft="@dimen/content_padding_standard"
android:paddingRight="@dimen/content_padding_standard">
android:gravity="center_vertical">
<net.osmand.telegram.ui.views.TextViewEx
android:id="@+id/stop_all_sharing_title"
<LinearLayout
android:id="@+id/stop_all_sharing_container"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/content_padding_standard"
android:layout_marginRight="@dimen/content_padding_standard"
android:layout_height="match_parent"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/stop_sharing_all"
android:textColor="?attr/ctrl_active_color"
android:textSize="@dimen/descr_text_size"
app:typeface="@string/font_roboto_medium" />
android:background="?attr/selectableItemBackground"
android:orientation="horizontal"
android:paddingLeft="@dimen/content_padding_standard"
android:paddingRight="@dimen/content_padding_standard">
<Switch
android:id="@+id/stop_all_sharing_switcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:clickable="false"
android:focusable="false"/>
<net.osmand.telegram.ui.views.TextViewEx
android:id="@+id/stop_all_sharing_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginEnd="@dimen/content_padding_standard"
android:layout_marginRight="@dimen/content_padding_standard"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/shared_string_disable"
android:textColor="?attr/ctrl_active_color"
android:textSize="@dimen/hint_text_size"
app:lastBaselineToBottomHeight="24dp"
app:typeface="@string/font_roboto_medium"/>
<Switch
android:id="@+id/stop_all_sharing_switcher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|center_vertical"
android:background="@null"
android:clickable="false"
android:focusable="false"/>
</LinearLayout>
<View
android:id="@+id/appbar_divider2"
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="?attr/card_divider_color"/>
<LinearLayout
android:id="@+id/sharing_status_container"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?attr/selectableItemBackground"
android:orientation="horizontal"
android:paddingLeft="@dimen/content_padding_standard"
android:paddingRight="@dimen/content_padding_standard">
<ImageView
android:id="@+id/sharing_status_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/content_padding_standard"
android:layout_marginRight="@dimen/content_padding_standard"
android:layout_marginTop="@dimen/content_padding_standard"
android:src="@drawable/ic_action_live_now"
android:tint="@color/ctrl_active_light"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:orientation="vertical">
<net.osmand.telegram.ui.views.TextViewEx
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/shared_string_status"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/list_item_description_text_size"
app:typeface="@string/font_roboto_regular"/>
<net.osmand.telegram.ui.views.TextViewEx
android:id="@+id/sharing_status_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:textColor="?attr/ctrl_active_color"
android:textSize="@dimen/hint_text_size"
app:lastBaselineToBottomHeight="@dimen/content_padding_standard"
app:typeface="@string/font_roboto_medium"
tools:text="@string/no_gps_connection"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
@ -231,11 +299,11 @@
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_height="match_parent">
tools:visibility="gone">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
@ -258,10 +326,10 @@
android:paddingRight="32dp"
android:text="@string/share_location"
android:textColor="@color/white"
app:typeface="@string/font_roboto_medium"
android:visibility="gone"
app:typeface="@string/font_roboto_medium"
tools:visibility="visible"/>
</FrameLayout>
</android.support.design.widget.CoordinatorLayout>

View file

@ -0,0 +1,106 @@
<?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">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/content_padding_standard"
android:layout_marginRight="@dimen/content_padding_standard"
android:layout_marginTop="@dimen/content_padding_standard"
tools:src="@drawable/ic_action_wifi_off"
tools:tint="@color/icon_light"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top"
android:orientation="horizontal">
<net.osmand.telegram.ui.views.TextViewEx
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textColor="?android:textColorPrimary"
android:textSize="@dimen/list_item_title_text_size"
app:firstBaselineToTopHeight="28sp"
app:typeface="@string/font_roboto_regular"
tools:text="@string/no_internet_connection"/>
<net.osmand.telegram.ui.views.TextViewEx
android:id="@+id/status_change_time"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="@dimen/content_padding_standard"
android:paddingRight="@dimen/content_padding_standard"
android:textColor="?android:textColorSecondary"
android:textSize="@dimen/list_item_description_text_size"
app:firstBaselineToTopHeight="26sp"
app:typeface="@string/font_roboto_regular"
tools:text="14:30"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<net.osmand.telegram.ui.views.TextViewEx
android:id="@+id/last_location_line"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/list_item_description_text_size"
app:firstBaselineToTopHeight="22dp"
app:lastBaselineToBottomHeight="20dp"
app:typeface="@string/font_roboto_regular"
tools:text="@string/last_available_location"/>
<net.osmand.telegram.ui.views.TextViewEx
android:id="@+id/last_location_line_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="@dimen/content_padding_half"
android:paddingRight="@dimen/content_padding_half"
android:textColor="?android:attr/textColorSecondary"
android:textSize="@dimen/list_item_description_text_size"
app:firstBaselineToTopHeight="22dp"
app:lastBaselineToBottomHeight="20dp"
app:typeface="@string/font_roboto_medium"
tools:text="14:24"/>
</LinearLayout>
<net.osmand.telegram.ui.views.TextViewEx
android:id="@+id/re_send_location"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:ellipsize="end"
android:maxLines="1"
android:text="@string/re_send_location"
android:textColor="?attr/ctrl_active_color"
android:textSize="@dimen/hint_text_size"
app:lastBaselineToBottomHeight="16dp"
app:typeface="@string/font_roboto_medium"/>
<View
android:id="@+id/bottom_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?attr/card_divider_color"/>
</LinearLayout>
</LinearLayout>

View file

@ -38,4 +38,7 @@
<color name="app_bar_title_light">#333333</color>
<color name="sharing_status_icon_error">#ee5622</color>
<color name="sharing_status_icon_success">#78cc5c</color>
</resources>

View file

@ -1,4 +1,15 @@
<resources>
<string name="re_send_location">Re-send location</string>
<string name="last_sent_location">Last sent location</string>
<string name="last_available_location">Last available location</string>
<string name="sharing_status">Sharing status</string>
<string name="sharing_enabled">Sharing: Enabled</string>
<string name="shared_string_status">Status</string>
<string name="no_gps_connection">No GPS connection</string>
<string name="sharing_success">Successfully sent and updated</string>
<string name="not_possible_to_send_to_chats">Not possible to send to chats:</string>
<string name="no_internet_connection">No internet connection</string>
<string name="shared_string_disable">Disable</string>
<string name="shared_string_save">Save</string>
<string name="add_device_descr">Enter your device id that you can find at https://live.osmand.net/device/ID</string>
<string name="device_id">Device id</string>

View file

@ -45,6 +45,9 @@ class TelegramLocationProvider(private val app: TelegramApplication) : SensorEve
var lastKnownLocation: net.osmand.Location? = null
private set
var lastKnownLocationTime: Long? = null
private set
val gpsInfo = GPSInfo()
private val locationListeners = ArrayList<TelegramLocationListener>()
@ -432,6 +435,7 @@ class TelegramLocationProvider(private val app: TelegramApplication) : SensorEve
updateGPSInfo(null)
}
if (location != null) {
lastKnownLocationTime = location.time
if (gpsSignalLost) {
gpsSignalLost = false
}

View file

@ -180,6 +180,7 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis
updateShareInfoHandler?.postDelayed({
if (isUsedByMyLocation(usedBy)) {
app().shareLocationHelper.updateSendLiveMessages()
app().settings.updateSharingStatusHistory()
startShareInfoUpdates()
}
}, UPDATE_LIVE_MESSAGES_INTERVAL_MS)
@ -296,6 +297,10 @@ class TelegramService : Service(), LocationListener, TelegramIncomingMessagesLis
app().settings.onDeleteLiveMessages(chatId, messages)
}
override fun onSendLiveLocationError(code: Int, message: String) {
Log.d(PlatformUtil.TAG, "Send live location error: $code - $message")
}
companion object {
const val USED_BY_MY_LOCATION: Int = 1

View file

@ -1,8 +1,11 @@
package net.osmand.telegram
import android.content.Context
import android.support.annotation.ColorRes
import android.support.annotation.DrawableRes
import android.support.annotation.StringRes
import android.text.SpannableStringBuilder
import android.text.style.ForegroundColorSpan
import net.osmand.data.LatLon
import net.osmand.telegram.helpers.OsmandAidlHelper
import net.osmand.telegram.helpers.TelegramHelper
@ -14,6 +17,8 @@ import org.drinkless.td.libcore.telegram.TdApi
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentLinkedQueue
val ADDITIONAL_ACTIVE_TIME_VALUES_SEC = listOf(15 * 60L, 30 * 60L, 60 * 60L, 180 * 60L)
@ -64,9 +69,11 @@ private const val SHARE_CHATS_INFO_KEY = "share_chats_info"
class TelegramSettings(private val app: TelegramApplication) {
private var shareChatsInfo = mutableMapOf<Long, ShareChatInfo>()
private var shareChatsInfo = ConcurrentHashMap<Long, ShareChatInfo>()
private var hiddenOnMapChats: Set<Long> = emptySet()
var sharingStatusChanges = ConcurrentLinkedQueue<SharingStatus>()
var shareDevicesIds = mutableMapOf<String, String>()
var currentSharingMode = ""
@ -91,7 +98,7 @@ class TelegramSettings(private val app: TelegramApplication) {
fun hasAnyChatToShareLocation() = shareChatsInfo.isNotEmpty()
fun isSharingLocationToChat(chatId: Long) = shareChatsInfo.contains(chatId)
fun isSharingLocationToChat(chatId: Long) = shareChatsInfo.containsKey(chatId)
fun hasAnyChatToShowOnMap() = !hiddenOnMapChats.containsAll(getLiveNowChats())
@ -102,9 +109,9 @@ class TelegramSettings(private val app: TelegramApplication) {
hiddenChats.intersect(presentChatIds)
hiddenOnMapChats = hiddenChats.toHashSet()
shareChatsInfo = shareChatsInfo.filter { (key, _) ->
shareChatsInfo = ConcurrentHashMap(shareChatsInfo.filter { (key, _) ->
presentChatIds.contains(key)
}.toMutableMap()
})
}
fun shareLocationToChat(
@ -123,6 +130,7 @@ class TelegramSettings(private val app: TelegramApplication) {
shareChatInfo = ShareChatInfo()
}
val currentTime = System.currentTimeMillis() / 1000
shareChatInfo.chatId = chatId
shareChatInfo.start = currentTime
if (shareChatInfo.livePeriod == -1L) {
shareChatInfo.livePeriod = lp
@ -149,6 +157,8 @@ class TelegramSettings(private val app: TelegramApplication) {
fun getChatsShareInfo() = shareChatsInfo
fun getLastSuccessfulSendTime() = shareChatsInfo.values.maxBy { it.lastSuccessfulSendTimeMs }?.lastSuccessfulSendTimeMs ?: -1
fun getChatLiveMessageExpireTime(chatId: Long): Long {
val shareInfo = shareChatsInfo[chatId]
return if (shareInfo != null) {
@ -195,7 +205,56 @@ class TelegramSettings(private val app: TelegramApplication) {
if (shareChatInfo != null && content is TdApi.MessageLocation) {
shareChatInfo.currentMessageId = message.id
shareChatInfo.lastSuccessfulLocation = LatLon(content.location.latitude, content.location.longitude)
shareChatInfo.lastSuccessfulSendTime = Math.max(message.editDate, message.date).toLong()
shareChatInfo.lastSuccessfulSendTimeMs = Math.max(message.editDate, message.date) *
1000L
}
}
fun updateSharingStatusHistory() {
val newSharingStatus = SharingStatus().apply {
statusChangeTime = System.currentTimeMillis()
statusType = if (!app.isInternetConnectionAvailable) {
SharingStatusType.NO_INTERNET
} else if (app.locationProvider.lastKnownLocation == null || !app.locationProvider.gpsInfo.fixed) {
SharingStatusType.NO_GPS
} else {
var sendChatErrors = false
shareChatsInfo.forEach { _, shareInfo ->
if ((statusChangeTime - shareInfo.lastSuccessfulSendTimeMs) > (sendMyLocInterval * 2) * 1000) {
sendChatErrors = true
locationTime = shareInfo.lastSuccessfulSendTimeMs
val title = app.telegramHelper.getChat(shareInfo.chatId)?.title
if (title != null) {
chatsTitles.add(title)
}
}
}
if (sendChatErrors) {
SharingStatusType.NOT_POSSIBLE_TO_SENT_TO_CHATS
} else {
SharingStatusType.SUCCESSFULLY_SENT
}
}
if (statusType == SharingStatusType.NO_INTERNET || statusType == SharingStatusType.SUCCESSFULLY_SENT) {
locationTime = getLastSuccessfulSendTime()
} else if (statusType == SharingStatusType.NO_GPS) {
locationTime = app.locationProvider.lastKnownLocationTime ?: -1
}
}
if (sharingStatusChanges.isNotEmpty()) {
val lastSharingStatus = sharingStatusChanges.last()
if (lastSharingStatus.statusType != newSharingStatus.statusType) {
sharingStatusChanges.add(newSharingStatus)
} else {
lastSharingStatus.apply {
statusChangeTime = newSharingStatus.statusChangeTime
locationTime = newSharingStatus.locationTime
chatsTitles = newSharingStatus.chatsTitles
}
}
} else {
sharingStatusChanges.add(newSharingStatus)
}
}
@ -453,6 +512,43 @@ class TelegramSettings(private val app: TelegramApplication) {
fun isSortByGroup() = this == SORT_BY_GROUP
}
enum class SharingStatusType(
@DrawableRes val iconId: Int,
@ColorRes val iconColorRes: Int,
@StringRes val titleId: Int,
@StringRes val descriptionId: Int,
val canResendLocation: Boolean
) {
NO_INTERNET(
R.drawable.ic_action_wifi_off,
R.color.sharing_status_icon_error,
R.string.no_internet_connection,
R.string.last_sent_location,
true
),
SUCCESSFULLY_SENT(
R.drawable.ic_action_share_location,
R.color.sharing_status_icon_success,
R.string.sharing_success,
R.string.last_sent_location,
false
),
NOT_POSSIBLE_TO_SENT_TO_CHATS(
R.drawable.ic_action_message_send_error,
R.color.sharing_status_icon_error,
R.string.not_possible_to_send_to_chats,
R.string.last_sent_location,
true
),
NO_GPS(
R.drawable.ic_action_location_off,
R.color.sharing_status_icon_error,
R.string.no_gps_connection,
R.string.last_available_location,
false
);
}
class DeviceBot {
var id: Long = -1
var userId: Long = -1
@ -462,6 +558,35 @@ class TelegramSettings(private val app: TelegramApplication) {
var data: String = ""
}
class SharingStatus {
var locationTime: Long = -1
var statusChangeTime: Long = -1
var chatsTitles: MutableList<String> = mutableListOf()
lateinit var statusType: SharingStatusType
fun getDescription(app: TelegramApplication): CharSequence {
return if (statusType != SharingStatusType.NOT_POSSIBLE_TO_SENT_TO_CHATS || chatsTitles.isEmpty()) {
app.getString(statusType.titleId)
} else {
val spannableString = SpannableStringBuilder(app.getString(statusType.titleId))
val iterator = chatsTitles.iterator()
while (iterator.hasNext()) {
val chatTitle = iterator.next()
val start = spannableString.length
val newSpannable = if (iterator.hasNext()) " @$chatTitle," else " @$chatTitle."
spannableString.append(newSpannable)
spannableString.setSpan(
ForegroundColorSpan(app.uiUtils.getActiveColor()),
start,
spannableString.length - 1,
0
)
}
spannableString
}
}
}
class ShareChatInfo {
var chatId = -1L
@ -472,7 +597,7 @@ class TelegramSettings(private val app: TelegramApplication) {
var userSetLivePeriod = -1L
var userSetLivePeriodStart = -1L
var lastSuccessfulLocation: LatLon? = null
var lastSuccessfulSendTime = -1L
var lastSuccessfulSendTimeMs = -1L
var shouldDeletePreviousMessage = false
var additionalActiveTime = ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0]

View file

@ -234,7 +234,6 @@ class TelegramHelper private constructor() {
fun onTelegramChatChanged(chat: TdApi.Chat)
fun onTelegramUserChanged(user: TdApi.User)
fun onTelegramError(code: Int, message: String)
fun onSendLiveLocationError(code: Int, message: String)
}
interface TelegramIncomingMessagesListener {
@ -246,6 +245,7 @@ class TelegramHelper private constructor() {
interface TelegramOutgoingMessagesListener {
fun onUpdateMessages(messages: List<TdApi.Message>)
fun onDeleteMessages(chatId: Long, messages: List<Long>)
fun onSendLiveLocationError(code: Int, message: String)
}
interface FullInfoUpdatesListener {
@ -619,7 +619,9 @@ class TelegramHelper private constructor() {
val error = obj as TdApi.Error
if (error.code != IGNORED_ERROR_CODE) {
needRefreshActiveLiveLocationMessages = true
listener?.onSendLiveLocationError(error.code, error.message)
outgoingMessagesListeners.forEach {
it.onSendLiveLocationError(error.code, error.message)
}
}
}
TdApi.Messages.CONSTRUCTOR -> {
@ -631,7 +633,9 @@ class TelegramHelper private constructor() {
}
onComplete?.invoke()
}
else -> listener?.onSendLiveLocationError(-1, "Receive wrong response from TDLib: $obj")
else -> outgoingMessagesListeners.forEach {
it.onSendLiveLocationError(-1, "Receive wrong response from TDLib: $obj")
}
}
requestingActiveLiveLocationMessages = false
}
@ -651,7 +655,9 @@ class TelegramHelper private constructor() {
val error = obj as TdApi.Error
if (error.code != IGNORED_ERROR_CODE) {
needRefreshActiveLiveLocationMessages = true
listener?.onSendLiveLocationError(error.code, error.message)
outgoingMessagesListeners.forEach {
it.onSendLiveLocationError(error.code, error.message)
}
}
}
}
@ -758,14 +764,18 @@ class TelegramHelper private constructor() {
val error = obj as TdApi.Error
if (error.code != IGNORED_ERROR_CODE) {
needRefreshActiveLiveLocationMessages = true
listener?.onSendLiveLocationError(error.code, error.message)
outgoingMessagesListeners.forEach {
it.onSendLiveLocationError(error.code, error.message)
}
}
}
TdApi.Message.CONSTRUCTOR -> {
if (obj is TdApi.Message) {
if (obj.sendingState?.constructor == TdApi.MessageSendingStateFailed.CONSTRUCTOR) {
needRefreshActiveLiveLocationMessages = true
listener?.onSendLiveLocationError(-1, "Live location message ${obj.id} failed to send")
outgoingMessagesListeners.forEach {
it.onSendLiveLocationError(-1, "Live location message ${obj.id} failed to send")
}
} else {
outgoingMessagesListeners.forEach {
it.onUpdateMessages(listOf(obj))

View file

@ -170,8 +170,6 @@ class LiveNowTabFragment : Fragment(), TelegramListener, TelegramIncomingMessage
override fun onTelegramError(code: Int, message: String) {}
override fun onSendLiveLocationError(code: Int, message: String) {}
override fun onReceiveChatLocationMessages(chatId: Long, vararg messages: TdApi.Message) {
app.runInUIThread { updateList() }
}

View file

@ -275,14 +275,6 @@ class MainActivity : AppCompatActivity(), TelegramListener, ActionButtonsListene
}
}
override fun onSendLiveLocationError(code: Int, message: String) {
log.error("Send live location error: $code - $message")
app.isInternetConnectionAvailable(true)
runOnUi {
listeners.forEach { it.get()?.onSendLiveLocationError(code, message) }
}
}
override fun onReceiveChatLocationMessages(chatId: Long, vararg messages: TdApi.Message) {
addGrayPhoto(chatId)
if (!app.showLocationHelper.showingLocation && settings.hasAnyChatToShowOnMap()) {

View file

@ -12,6 +12,8 @@ import android.support.v4.app.Fragment
import android.support.v4.content.ContextCompat
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
import android.view.*
import android.view.animation.LinearInterpolator
import android.widget.*
@ -57,6 +59,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
private lateinit var description: TextView
private lateinit var searchBox: FrameLayout
private lateinit var stopSharingSwitcher: Switch
private lateinit var sharingStatusDescription: TextView
private lateinit var startSharingBtn: View
private lateinit var searchBoxBg: GradientDrawable
@ -71,7 +74,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
private var actionButtonsListener: ActionButtonsListener? = null
private var sharingMode = false
private var updateEnable: Boolean = false
override fun onCreateView(
@ -90,7 +93,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
searchBoxSidesMargin = resources.getDimensionPixelSize(R.dimen.content_padding_half)
sharingMode = settings.hasAnyChatToShareLocation()
savedInstanceState?.apply {
selectedChats.addAll(getLongArray(SELECTED_CHATS_KEY).toSet())
if (selectedChats.isNotEmpty()) {
@ -132,6 +135,14 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
AndroidUtils.addStatusBarPadding19v(context, this)
}
mainView.findViewById<TextView>(R.id.status_title).apply {
val sharingStatus = getString(R.string.sharing_enabled)
val spannable = SpannableString(sharingStatus)
spannable.setSpan(ForegroundColorSpan(app.uiUtils.getActiveColor()),
sharingStatus.indexOf(" "), sharingStatus.length, 0)
text = spannable
}
textContainer = mainView.findViewById<LinearLayout>(R.id.text_container).apply {
if (Build.VERSION.SDK_INT >= 16) {
layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
@ -181,8 +192,17 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
}
mainView.findViewById<View>(R.id.sharing_status_container).setOnClickListener {
settings.updateSharingStatusHistory()
fragmentManager?.also { fm ->
SharingStatusBottomSheet.showInstance(fm, this)
}
}
stopSharingSwitcher = mainView.findViewById(R.id.stop_all_sharing_switcher)
sharingStatusDescription = mainView.findViewById(R.id.sharing_status_description)
startSharingBtn = mainView.findViewById<View>(R.id.start_sharing_btn).apply {
visibility = if (sharingMode) View.VISIBLE else View.GONE
setOnClickListener {
@ -191,7 +211,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
updateContent()
}
}
return mainView
}
@ -208,7 +228,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
super.onPause()
updateEnable = false
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putLongArray(SELECTED_CHATS_KEY, selectedChats.toLongArray())
@ -269,9 +289,6 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
override fun onTelegramError(code: Int, message: String) {
}
override fun onSendLiveLocationError(code: Int, message: String) {
}
fun onPrimaryBtnClick() {
if (selectedChats.isNotEmpty()) {
val fm = fragmentManager ?: return
@ -306,7 +323,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
}, ADAPTER_UPDATE_INTERVAL_MIL)
}
private fun animateStartSharingBtn(show: Boolean) {
if (startSharingBtn.visibility == View.VISIBLE) {
val scale = if (show) 1f else 0f
@ -318,7 +335,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
.start()
}
}
private fun clearSelection() {
selectedChats.clear()
adapter.notifyDataSetChanged()
@ -394,6 +411,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
private fun updateContent() {
updateSharingStatus()
updateSharingMode()
updateList()
}
@ -409,6 +427,15 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
appBarScrollRange = -1
}
private fun updateSharingStatus() {
if (sharingMode) {
if (settings.sharingStatusChanges.isEmpty()) {
settings.updateSharingStatusHistory()
}
sharingStatusDescription.text = settings.sharingStatusChanges.last().getDescription(app)
}
}
private fun updateList() {
val chats: MutableList<TdApi.Chat> = mutableListOf()
val currentUser = telegramHelper.getCurrentUser()
@ -441,7 +468,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
list.sortWith(Comparator<TdApi.Chat> { o1, o2 -> o1.title.compareTo(o2.title) })
return list
}
inner class MyLocationListAdapter : RecyclerView.Adapter<MyLocationListAdapter.BaseViewHolder>() {
var chats = mutableListOf<TdApi.Chat>()
set(value) {
@ -540,7 +567,7 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
}
val expiresIn = settings.getChatLiveMessageExpireTime(chat.id)
holder.textInArea?.apply {
val time = shareInfo?.additionalActiveTime ?: ADDITIONAL_ACTIVE_TIME_VALUES_SEC[0]
visibility = View.VISIBLE

View file

@ -0,0 +1,97 @@
package net.osmand.telegram.ui
import android.os.Bundle
import android.support.design.widget.BottomSheetBehavior
import android.support.v4.app.DialogFragment
import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import net.osmand.telegram.R
import net.osmand.telegram.TelegramApplication
import net.osmand.telegram.TelegramSettings
import net.osmand.telegram.ui.views.BottomSheetDialog
import net.osmand.telegram.utils.OsmandFormatter
class SharingStatusBottomSheet : DialogFragment() {
private val app: TelegramApplication
get() = activity?.application as TelegramApplication
private val settings get() = app.settings
private val uiUtils get() = app.uiUtils
override fun onCreateDialog(savedInstanceState: Bundle?) = BottomSheetDialog(context!!)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val mainView = inflater.inflate(R.layout.bottom_sheet_sharing_status, container, false)
mainView.findViewById<View>(R.id.scroll_view_container).setOnClickListener { dismiss() }
BottomSheetBehavior.from(mainView.findViewById<View>(R.id.scroll_view))
.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
dismiss()
}
}
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
})
val itemsCont = mainView.findViewById<ViewGroup>(R.id.items_container)
settings.sharingStatusChanges.reversed().forEach { sharingStatus ->
inflater.inflate(R.layout.item_with_four_text_lines, itemsCont, false).apply {
val sharingStatusType = sharingStatus.statusType
findViewById<ImageView>(R.id.icon).setImageDrawable(uiUtils.getIcon(sharingStatusType.iconId, sharingStatusType.iconColorRes))
findViewById<TextView>(R.id.title).text = sharingStatus.getDescription(app)
findViewById<TextView>(R.id.status_change_time).text =
OsmandFormatter.getFormattedTime(sharingStatus.statusChangeTime, false)
val time = sharingStatus.locationTime
findViewById<TextView>(R.id.last_location_line).text = getString(sharingStatusType.descriptionId)
if (time > 0) {
val sentTime = OsmandFormatter.getFormattedTime(time, false)
findViewById<TextView>(R.id.last_location_line_time).text = sentTime
} else {
findViewById<TextView>(R.id.last_location_line_time).text = "-"
}
if (sharingStatusType.canResendLocation) {
findViewById<TextView>(R.id.re_send_location).apply {
setOnClickListener {
app.forceUpdateMyLocation()
dismiss()
}
}
} else {
findViewById<TextView>(R.id.re_send_location).visibility = View.GONE
}
itemsCont.addView(this)
}
}
mainView.findViewById<TextView>(R.id.secondary_btn).apply {
setText(R.string.shared_string_close)
setOnClickListener { dismiss() }
}
return mainView
}
companion object {
const val SHARING_STATUS_REQUEST_CODE = 5
private const val TAG = "SharingStatusBottomSheet"
fun showInstance(fm: FragmentManager, target: Fragment): Boolean {
return try {
SharingStatusBottomSheet().apply {
setTargetFragment(target, SHARING_STATUS_REQUEST_CODE)
show(fm, TAG)
}
true
} catch (e: RuntimeException) {
false
}
}
}
}

View file

@ -21,7 +21,7 @@ object OsmandFormatter {
private val fixed1 = DecimalFormat("0.0")
private const val SHORT_TIME_FORMAT = "%02d:%02d"
private const val SIMPLE_TIME_OF_DAY_FORMAT = "HH:mm"
private const val SIMPLE_TIME_OF_DAY_FORMAT = "HH:mm:ss"
private const val SIMPLE_DATE_FORMAT = "dd MMM HH:mm:ss"
private const val MIN_DURATION_FOR_DATE_FORMAT = 48 * 60 * 60
@ -62,9 +62,13 @@ object OsmandFormatter {
}
}
fun getFormattedTime(seconds: Long): String {
fun getFormattedTime(milliseconds: Long, useCurrentTime: Boolean = true): String {
val calendar = Calendar.getInstance()
calendar.timeInMillis = System.currentTimeMillis() + (seconds * 1000)
if (useCurrentTime) {
calendar.timeInMillis = System.currentTimeMillis() + milliseconds
} else {
calendar.timeInMillis = milliseconds
}
return if (isSameDay(calendar, Calendar.getInstance())) {
SimpleDateFormat(SIMPLE_TIME_OF_DAY_FORMAT, Locale.getDefault()).format(calendar.time)
} else {

View file

@ -107,6 +107,10 @@ class UiUtils(private val app: TelegramApplication) {
return getDrawable(id, if (isLightContent) R.color.ctrl_active_light else 0)
}
fun getActiveColor():Int {
return ContextCompat.getColor(app, if (isLightContent) R.color.ctrl_active_light else 0)
}
fun getIcon(@DrawableRes id: Int): Drawable? {
return getDrawable(id, 0)
}