Telegram sharing status init
This commit is contained in:
parent
519827262c
commit
0ff05fd0a6
15 changed files with 595 additions and 74 deletions
67
OsmAnd-telegram/res/layout/bottom_sheet_sharing_status.xml
Normal file
67
OsmAnd-telegram/res/layout/bottom_sheet_sharing_status.xml
Normal 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>
|
|
@ -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,20 +168,18 @@
|
|||
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"/>
|
||||
|
@ -198,8 +198,15 @@
|
|||
android:id="@+id/stop_all_sharing_row"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/action_bar_height"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/stop_all_sharing_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard">
|
||||
|
||||
|
@ -207,35 +214,96 @@
|
|||
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/stop_sharing_all"
|
||||
android:text="@string/shared_string_disable"
|
||||
android:textColor="?attr/ctrl_active_color"
|
||||
android:textSize="@dimen/descr_text_size"
|
||||
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>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</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,8 +326,8 @@
|
|||
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>
|
||||
|
|
106
OsmAnd-telegram/res/layout/item_with_four_text_lines.xml
Normal file
106
OsmAnd-telegram/res/layout/item_with_four_text_lines.xml
Normal 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>
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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() }
|
||||
}
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue