Merge pull request #6221 from osmandapp/AddSharingDevice
Add ability to add new sharing devices
This commit is contained in:
commit
d2c56bb451
11 changed files with 767 additions and 95 deletions
127
OsmAnd-telegram/res/layout/bottom_sheet_add_new_device.xml
Normal file
127
OsmAnd-telegram/res/layout/bottom_sheet_add_new_device.xml
Normal file
|
@ -0,0 +1,127 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
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.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="wrap_content"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard"
|
||||
android:text="@string/add_device"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/list_item_title_text_size"
|
||||
app:firstBaselineToTopHeight="28sp"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard"
|
||||
android:text="@string/enter_device_name_description"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size"
|
||||
app:firstBaselineToTopHeight="28sp"
|
||||
app:lastBaselineToBottomHeight="16sp"
|
||||
app:typeface="@string/font_roboto_regular" />
|
||||
|
||||
<studio.carbonylgroup.textfieldboxes.TextFieldBoxes
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard"
|
||||
app:hasClearButton="true"
|
||||
app:labelText="@string/device_name">
|
||||
|
||||
<studio.carbonylgroup.textfieldboxes.ExtendedEditText
|
||||
android:id="@+id/edit_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="text" />
|
||||
|
||||
</studio.carbonylgroup.textfieldboxes.TextFieldBoxes>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error_text_descr"
|
||||
android:layout_width="match_parent"
|
||||
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_half"
|
||||
android:letterSpacing="@dimen/text_description_letter_spacing"
|
||||
android:lineSpacingMultiplier="@dimen/text_description_line_spacing_multiplier"
|
||||
android:textSize="@dimen/hint_text_size"
|
||||
android:visibility="invisible"
|
||||
tools:text="@string/device_name_cannot_be_empty" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</android.support.v4.widget.NestedScrollView>
|
||||
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/buttons_bottom_bar_height"
|
||||
android:background="?attr/card_bg_color"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="@dimen/content_padding_half"
|
||||
android:paddingRight="@dimen/content_padding_half">
|
||||
|
||||
<include
|
||||
layout="@layout/secondary_btn"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<View
|
||||
android:layout_width="@dimen/content_padding_half"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1">
|
||||
|
||||
<include
|
||||
layout="@layout/primary_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="@dimen/progress_bar_size_small"
|
||||
android:layout_height="@dimen/progress_bar_size_small"
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -95,11 +95,13 @@
|
|||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/share_as_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingLeft="@dimen/content_padding_standard"
|
||||
android:paddingRight="@dimen/content_padding_standard"
|
||||
android:text="@string/share_location_as_descr"
|
||||
android:text="@string/share_location_as_description"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/list_item_description_text_size"
|
||||
app:firstBaselineToTopHeight="20sp"
|
||||
|
@ -120,6 +122,38 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/add_new_device_btn"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dialog_button_height"
|
||||
android:layout_marginBottom="@dimen/content_padding_standard"
|
||||
android:layout_marginLeft="@dimen/content_padding_half"
|
||||
android:layout_marginRight="@dimen/content_padding_half"
|
||||
android:background="@drawable/btn_round"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingLeft="@dimen/content_padding_half"
|
||||
android:paddingRight="@dimen/content_padding_half">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/add_new_device_icon"
|
||||
android:layout_width="@dimen/list_item_icon_size"
|
||||
android:layout_height="@dimen/list_item_icon_size"
|
||||
tools:src="@drawable/ic_action_add"
|
||||
tools:tint="@color/icon_light" />
|
||||
|
||||
<net.osmand.telegram.ui.views.TextViewEx
|
||||
android:id="@+id/add_new_device_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="@dimen/content_padding_big"
|
||||
android:layout_marginRight="@dimen/content_padding_big"
|
||||
android:text="@string/add_device"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="@dimen/list_item_title_text_size"
|
||||
app:typeface="@string/font_roboto_medium" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/list_item_divider" />
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
<resources>
|
||||
<string name="enter_another_device_name">Enter another name, you already have the device with the same name</string>
|
||||
<string name="device_added_successfully">%1$s added successfully.</string>
|
||||
<string name="shared_string_add">Add</string>
|
||||
<string name="error_adding_new_device">Error adding new device</string>
|
||||
<string name="enter_device_name_description">Enter a name for your new device. Max length 200 symbols.</string>
|
||||
<string name="device_name_is_too_long">Device name is too long</string>
|
||||
<string name="device_name_cannot_be_empty">Device name cannot be empty</string>
|
||||
<string name="device_name">Device name</string>
|
||||
<string name="shared_string_hide">Hide</string>
|
||||
<string name="share_location_as_description_second_line">You can create and view the Device ID in the telegram client using the %1$s chat bot. %2$s</string>
|
||||
<string name="share_location_as_description">If you want to connect multiple devices to one telegram account, you need to use different Device to share your location.</string>
|
||||
<string name="add_new_device_description">Last updated location:</string>
|
||||
<string name="last_updated_location">Last updated location:</string>
|
||||
<string name="successfully_sent_and_updated">Successfully sent and updated</string>
|
||||
<string name="not_possible_to_send_to_telegram_chats">Not possible to send to Telegram chats:</string>
|
||||
|
|
|
@ -11,6 +11,7 @@ import net.osmand.data.LatLon
|
|||
import net.osmand.telegram.helpers.OsmandAidlHelper
|
||||
import net.osmand.telegram.helpers.TelegramHelper
|
||||
import net.osmand.telegram.utils.AndroidUtils
|
||||
import net.osmand.telegram.utils.OsmandApiUtils
|
||||
import net.osmand.telegram.utils.OsmandFormatter
|
||||
import net.osmand.telegram.utils.OsmandFormatter.MetricsConstants
|
||||
import net.osmand.telegram.utils.OsmandFormatter.SpeedConstants
|
||||
|
@ -23,6 +24,8 @@ import java.util.concurrent.ConcurrentLinkedQueue
|
|||
|
||||
val ADDITIONAL_ACTIVE_TIME_VALUES_SEC = listOf(15 * 60L, 30 * 60L, 60 * 60L, 180 * 60L)
|
||||
|
||||
const val SHARE_DEVICES_KEY = "devices"
|
||||
|
||||
private val SEND_MY_LOC_VALUES_SEC =
|
||||
listOf(1L, 2L, 3L, 5L, 10L, 15L, 30L, 60L, 90L, 2 * 60L, 3 * 60L, 5 * 60L)
|
||||
private val STALE_LOC_VALUES_SEC =
|
||||
|
@ -76,10 +79,10 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
|
||||
private var shareChatsInfo = ConcurrentHashMap<Long, ShareChatInfo>()
|
||||
private var hiddenOnMapChats: Set<Long> = emptySet()
|
||||
private var shareDevices: Set<DeviceBot> = emptySet()
|
||||
|
||||
var sharingStatusChanges = ConcurrentLinkedQueue<SharingStatus>()
|
||||
|
||||
var shareDevicesIds = mutableMapOf<String, String>()
|
||||
var currentSharingMode = ""
|
||||
|
||||
var metricsConstants = MetricsConstants.KILOMETERS_AND_METERS
|
||||
|
@ -151,16 +154,24 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
}
|
||||
|
||||
fun updateShareDevicesIds(list: List<DeviceBot>) {
|
||||
shareDevicesIds.clear()
|
||||
list.forEach {
|
||||
shareDevicesIds[it.externalId] = it.deviceName
|
||||
}
|
||||
shareDevices = list.toHashSet()
|
||||
}
|
||||
|
||||
fun getChatLivePeriod(chatId: Long) = shareChatsInfo[chatId]?.livePeriod
|
||||
|
||||
fun getChatsShareInfo() = shareChatsInfo
|
||||
|
||||
fun getShareDevices() = shareDevices
|
||||
|
||||
fun containsShareDeviceWithName(name: String): Boolean {
|
||||
shareDevices.forEach {
|
||||
if (it.deviceName == name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun getLastSuccessfulSendTime() = shareChatsInfo.values.maxBy { it.lastSuccessfulSendTimeMs }?.lastSuccessfulSendTimeMs ?: -1
|
||||
|
||||
fun stopSharingLocationToChats() {
|
||||
|
@ -216,11 +227,15 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
statusChangeTime = newSharingStatus.statusChangeTime
|
||||
locationTime = newSharingStatus.locationTime
|
||||
chatsTitles = newSharingStatus.chatsTitles
|
||||
title = newSharingStatus.title
|
||||
|
||||
if (statusType == SharingStatusType.INITIALIZING
|
||||
&& newSharingStatus.statusType == SharingStatusType.INITIALIZING
|
||||
&& !lastSharingStatus.description.contains(newSharingStatus.description)) {
|
||||
lastSharingStatus.description = "${lastSharingStatus.description}, ${newSharingStatus.description}"
|
||||
&& newSharingStatus.statusType == SharingStatusType.INITIALIZING) {
|
||||
if (!description.contains(newSharingStatus.description)) {
|
||||
description = "$description, ${newSharingStatus.description}"
|
||||
}
|
||||
} else {
|
||||
description = newSharingStatus.description
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -278,7 +293,7 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
locationTime = getLastSuccessfulSendTime()
|
||||
title = app.getString(R.string.successfully_sent_and_updated)
|
||||
description = app.getString(R.string.last_updated_location)
|
||||
statusType = SharingStatusType.SUCCESSFULLY_SENT
|
||||
statusType = SharingStatusType.SENDING
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -332,22 +347,14 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
|
||||
edit.putBoolean(BATTERY_OPTIMISATION_ASKED, batteryOptimisationAsked)
|
||||
|
||||
try {
|
||||
val jArray = JSONArray()
|
||||
shareChatsInfo.forEach { (chatId, chatInfo) ->
|
||||
val obj = JSONObject()
|
||||
obj.put(ShareChatInfo.CHAT_ID_KEY, chatId)
|
||||
obj.put(ShareChatInfo.START_KEY, chatInfo.start)
|
||||
obj.put(ShareChatInfo.LIVE_PERIOD_KEY, chatInfo.livePeriod)
|
||||
obj.put(ShareChatInfo.LIMIT_KEY, chatInfo.currentMessageLimit)
|
||||
obj.put(ShareChatInfo.CURRENT_MESSAGE_ID_KEY, chatInfo.currentMessageId)
|
||||
obj.put(ShareChatInfo.USER_SET_LIVE_PERIOD_KEY, chatInfo.userSetLivePeriod)
|
||||
obj.put(ShareChatInfo.USER_SET_LIVE_PERIOD_START_KEY, chatInfo.userSetLivePeriodStart)
|
||||
jArray.put(obj)
|
||||
}
|
||||
val jArray = convertShareChatsInfoToJson()
|
||||
if (jArray != null) {
|
||||
edit.putString(SHARE_CHATS_INFO_KEY, jArray.toString())
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
val jsonObject = convertShareDevicesToJson()
|
||||
if (jsonObject != null) {
|
||||
edit.putString(SHARE_DEVICES_KEY, jsonObject.toString())
|
||||
}
|
||||
|
||||
edit.apply()
|
||||
|
@ -376,6 +383,8 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
e.printStackTrace()
|
||||
}
|
||||
|
||||
parseShareDevices(prefs.getString(SHARE_DEVICES_KEY, ""))
|
||||
|
||||
val sendMyLocDef = SEND_MY_LOC_VALUES_SEC[SEND_MY_LOC_DEFAULT_INDEX]
|
||||
sendMyLocInterval = prefs.getLong(SEND_MY_LOC_INTERVAL_KEY, sendMyLocDef)
|
||||
val staleLocDef = STALE_LOC_VALUES_SEC[STALE_LOC_DEFAULT_INDEX]
|
||||
|
@ -394,6 +403,48 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
batteryOptimisationAsked = prefs.getBoolean(BATTERY_OPTIMISATION_ASKED,false)
|
||||
}
|
||||
|
||||
private fun convertShareDevicesToJson():JSONObject?{
|
||||
return try {
|
||||
val jsonObject = JSONObject()
|
||||
val jArray = JSONArray()
|
||||
shareDevices.forEach { device ->
|
||||
val obj = JSONObject()
|
||||
obj.put(DeviceBot.DEVICE_ID, device.id)
|
||||
obj.put(DeviceBot.USER_ID, device.userId)
|
||||
obj.put(DeviceBot.CHAT_ID, device.chatId)
|
||||
obj.put(DeviceBot.DEVICE_NAME, device.deviceName)
|
||||
obj.put(DeviceBot.EXTERNAL_ID, device.externalId)
|
||||
obj.put(DeviceBot.DATA, JSONObject(device.data))
|
||||
jArray.put(obj)
|
||||
}
|
||||
jsonObject.put(SHARE_DEVICES_KEY, jArray)
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun convertShareChatsInfoToJson(): JSONArray? {
|
||||
return try {
|
||||
val jArray = JSONArray()
|
||||
shareChatsInfo.forEach { (chatId, chatInfo) ->
|
||||
val obj = JSONObject()
|
||||
obj.put(ShareChatInfo.CHAT_ID_KEY, chatId)
|
||||
obj.put(ShareChatInfo.START_KEY, chatInfo.start)
|
||||
obj.put(ShareChatInfo.LIVE_PERIOD_KEY, chatInfo.livePeriod)
|
||||
obj.put(ShareChatInfo.LIMIT_KEY, chatInfo.currentMessageLimit)
|
||||
obj.put(ShareChatInfo.CURRENT_MESSAGE_ID_KEY, chatInfo.currentMessageId)
|
||||
obj.put(ShareChatInfo.USER_SET_LIVE_PERIOD_KEY, chatInfo.userSetLivePeriod)
|
||||
obj.put(ShareChatInfo.USER_SET_LIVE_PERIOD_START_KEY, chatInfo.userSetLivePeriodStart)
|
||||
jArray.put(obj)
|
||||
}
|
||||
jArray
|
||||
} catch (e: JSONException) {
|
||||
e.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseShareChatsInfo(json: JSONArray) {
|
||||
for (i in 0 until json.length()) {
|
||||
val obj = json.getJSONObject(i)
|
||||
|
@ -410,6 +461,10 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
}
|
||||
}
|
||||
|
||||
private fun parseShareDevices(json: String) {
|
||||
shareDevices = OsmandApiUtils.parseJsonContents(json).toHashSet()
|
||||
}
|
||||
|
||||
private fun getLiveNowChats() = app.telegramHelper.getMessagesByChatIds(locHistoryTime).keys
|
||||
|
||||
private fun updatePrefs() {
|
||||
|
@ -567,11 +622,6 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
R.color.sharing_status_icon_error,
|
||||
true
|
||||
),
|
||||
SUCCESSFULLY_SENT(
|
||||
R.drawable.ic_action_share_location,
|
||||
R.color.sharing_status_icon_success,
|
||||
false
|
||||
),
|
||||
SENDING(
|
||||
R.drawable.ic_action_share_location,
|
||||
R.color.sharing_status_icon_success,
|
||||
|
@ -601,6 +651,16 @@ class TelegramSettings(private val app: TelegramApplication) {
|
|||
var deviceName: String = ""
|
||||
var externalId: String = ""
|
||||
var data: String = ""
|
||||
|
||||
companion object {
|
||||
|
||||
internal const val DEVICE_ID = "id"
|
||||
internal const val USER_ID = "userId"
|
||||
internal const val CHAT_ID = "chatId"
|
||||
internal const val DEVICE_NAME = "deviceName"
|
||||
internal const val EXTERNAL_ID = "externalId"
|
||||
internal const val DATA = "data"
|
||||
}
|
||||
}
|
||||
|
||||
class SharingStatus {
|
||||
|
|
|
@ -5,6 +5,7 @@ import net.osmand.PlatformUtil
|
|||
import net.osmand.telegram.TelegramApplication
|
||||
import net.osmand.telegram.notifications.TelegramNotification.NotificationType
|
||||
import net.osmand.telegram.utils.AndroidNetworkUtils
|
||||
import net.osmand.telegram.utils.BASE_URL
|
||||
|
||||
private const val USER_SET_LIVE_PERIOD_DELAY_MS = 5000 // 5 sec
|
||||
|
||||
|
@ -51,8 +52,8 @@ class ShareLocationHelper(private val app: TelegramApplication) {
|
|||
if (user != null && sharingMode == user.id.toString()) {
|
||||
app.telegramHelper.sendLiveLocationMessage(chatsShareInfo, location.latitude, location.longitude)
|
||||
} else if (sharingMode.isNotEmpty()) {
|
||||
val url = "https://live.osmand.net/device/$sharingMode/send?lat=${location.latitude}&lon=${location.longitude}"
|
||||
AndroidNetworkUtils.sendRequestAsync(url, null)
|
||||
val url = "$BASE_URL/device/$sharingMode/send?lat=${location.latitude}&lon=${location.longitude}"
|
||||
AndroidNetworkUtils.sendRequestAsync(app, url, null, "Send Location", false, false, null)
|
||||
}
|
||||
}
|
||||
lastLocationMessageSentTime = System.currentTimeMillis()
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
package net.osmand.telegram.ui
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.BottomSheetBehavior
|
||||
import android.support.v4.app.Fragment
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.EditText
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import net.osmand.telegram.R
|
||||
import net.osmand.telegram.TelegramSettings
|
||||
import net.osmand.telegram.ui.views.BottomSheetDialog
|
||||
import net.osmand.telegram.utils.AndroidNetworkUtils
|
||||
import net.osmand.telegram.utils.OsmandApiUtils
|
||||
import org.drinkless.td.libcore.telegram.TdApi
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
|
||||
class AddNewDeviceBottomSheet : BaseDialogFragment() {
|
||||
|
||||
private lateinit var editText: EditText
|
||||
private lateinit var errorTextDescription: TextView
|
||||
private lateinit var primaryBtn: TextView
|
||||
private lateinit var progressBar: ProgressBar
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val dialog = BottomSheetDialog(context!!)
|
||||
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
|
||||
return dialog
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val mainView = inflater.inflate(R.layout.bottom_sheet_add_new_device, 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) {}
|
||||
})
|
||||
|
||||
editText = mainView.findViewById<EditText>(R.id.edit_text).apply {
|
||||
addTextChangedListener(object :
|
||||
TextWatcher {
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
updateErrorTextDescription(s.toString())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
errorTextDescription = mainView.findViewById<TextView>(R.id.error_text_descr)
|
||||
|
||||
progressBar = mainView.findViewById<ProgressBar>(R.id.progressBar).apply {
|
||||
indeterminateDrawable.setColorFilter(ContextCompat.getColor(app, R.color.primary_btn_text_light), android.graphics.PorterDuff.Mode.MULTIPLY)
|
||||
}
|
||||
|
||||
mainView.findViewById<TextView>(R.id.secondary_btn).apply {
|
||||
setText(R.string.shared_string_cancel)
|
||||
setOnClickListener { dismiss() }
|
||||
}
|
||||
|
||||
primaryBtn = mainView.findViewById<TextView>(R.id.primary_btn).apply {
|
||||
setText(R.string.shared_string_add)
|
||||
setOnClickListener {
|
||||
val deviceName = editText.text.toString()
|
||||
updateErrorTextDescription(deviceName)
|
||||
if (deviceName.isNotEmpty() && deviceName.length < MAX_DEVICE_NAME_LENGTH
|
||||
&& !app.settings.containsShareDeviceWithName(deviceName)) {
|
||||
val user = app.telegramHelper.getCurrentUser()
|
||||
if (user != null) {
|
||||
updatePrimaryBtnAndProgress(true)
|
||||
createNewDeviceWithName(user, deviceName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mainView
|
||||
}
|
||||
|
||||
private fun createNewDeviceWithName(user: TdApi.User, deviceName: String) {
|
||||
OsmandApiUtils.createNewDevice(app, user, app.telegramHelper.isBot(user.id), deviceName, 0,
|
||||
object : AndroidNetworkUtils.OnRequestResultListener {
|
||||
override fun onResult(result: String?) {
|
||||
updatePrimaryBtnAndProgress(false)
|
||||
val deviceBot = getDeviceFromJson(result)
|
||||
if (deviceBot != null) {
|
||||
targetFragment?.also { target ->
|
||||
val intent = Intent().putExtra(DEVICE_NAME, deviceBot.deviceName).putExtra(DEVICE_EXTERNAL_ID, deviceBot.externalId)
|
||||
target.onActivityResult(targetRequestCode, NEW_DEVICE_REQUEST_CODE, intent)
|
||||
}
|
||||
dismiss()
|
||||
} else {
|
||||
updateErrorTextDescription(null)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun updateErrorTextDescription(text: String?) {
|
||||
when {
|
||||
text == null -> {
|
||||
errorTextDescription.visibility = View.VISIBLE
|
||||
errorTextDescription.text = getString(R.string.error_adding_new_device)
|
||||
}
|
||||
text.isEmpty() -> {
|
||||
errorTextDescription.visibility = View.VISIBLE
|
||||
errorTextDescription.text = getString(R.string.device_name_cannot_be_empty)
|
||||
}
|
||||
text.length > MAX_DEVICE_NAME_LENGTH -> {
|
||||
errorTextDescription.visibility = View.VISIBLE
|
||||
errorTextDescription.text = getString(R.string.device_name_is_too_long)
|
||||
}
|
||||
app.settings.containsShareDeviceWithName(text.toString()) -> {
|
||||
errorTextDescription.visibility = View.VISIBLE
|
||||
errorTextDescription.text = getString(R.string.enter_another_device_name)
|
||||
}
|
||||
else -> errorTextDescription.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePrimaryBtnAndProgress(showProgress: Boolean) {
|
||||
if (showProgress) {
|
||||
progressBar.visibility = View.VISIBLE
|
||||
primaryBtn.text = ""
|
||||
} else {
|
||||
progressBar.visibility = View.GONE
|
||||
primaryBtn.setText(R.string.shared_string_add)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDeviceFromJson(json: String?): TelegramSettings.DeviceBot? {
|
||||
var device: TelegramSettings.DeviceBot? = null
|
||||
if (json != null) {
|
||||
device = try {
|
||||
val jsonResult = JSONObject(json)
|
||||
val status = jsonResult.getString("status")
|
||||
if (status == "OK") {
|
||||
OsmandApiUtils.parseDeviceBot(jsonResult.getJSONObject("device"))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
return device
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val NEW_DEVICE_REQUEST_CODE = 5
|
||||
const val DEVICE_NAME = "DEVICE_NAME"
|
||||
const val DEVICE_EXTERNAL_ID = "DEVICE_EXTERNAL_ID"
|
||||
const val MAX_DEVICE_NAME_LENGTH = 200
|
||||
|
||||
private const val TAG = "AddNewDeviceBottomSheet"
|
||||
fun showInstance(fm: FragmentManager, target: Fragment): Boolean {
|
||||
return try {
|
||||
AddNewDeviceBottomSheet().apply {
|
||||
setTargetFragment(target, NEW_DEVICE_REQUEST_CODE)
|
||||
show(fm, TAG)
|
||||
}
|
||||
true
|
||||
} catch (e: RuntimeException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,14 @@
|
|||
package net.osmand.telegram.ui
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v7.widget.ListPopupWindow
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
|
@ -14,6 +17,7 @@ import android.widget.*
|
|||
import net.osmand.telegram.R
|
||||
import net.osmand.telegram.TelegramSettings
|
||||
import net.osmand.telegram.TelegramSettings.DurationPref
|
||||
import net.osmand.telegram.helpers.TelegramHelper.Companion.OSMAND_BOT_USERNAME
|
||||
import net.osmand.telegram.helpers.TelegramUiHelper
|
||||
import net.osmand.telegram.utils.AndroidUtils
|
||||
import org.drinkless.td.libcore.telegram.TdApi
|
||||
|
@ -21,6 +25,10 @@ import org.drinkless.td.libcore.telegram.TdApi
|
|||
class SettingsDialogFragment : BaseDialogFragment() {
|
||||
|
||||
private val uiUtils get() = app.uiUtils
|
||||
private lateinit var shareAsContainer: ViewGroup
|
||||
private lateinit var shareAsDescription: TextView
|
||||
|
||||
private var shareAsDescriptionHidden = true
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
@ -65,6 +73,36 @@ class SettingsDialogFragment : BaseDialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
shareAsDescription = mainView.findViewById<TextView>(R.id.share_as_description).apply {
|
||||
text = getText(R.string.share_location_as_description)
|
||||
setOnClickListener {
|
||||
updateShareAsDescription()
|
||||
}
|
||||
}
|
||||
|
||||
shareAsContainer = mainView.findViewById(R.id.share_as_container)
|
||||
val user = telegramHelper.getCurrentUser()
|
||||
if (user != null) {
|
||||
addItemToContainer(inflater, shareAsContainer, user.id.toString(), TelegramUiHelper.getUserName(user))
|
||||
}
|
||||
settings.getShareDevices().forEach {
|
||||
addItemToContainer(inflater, shareAsContainer, it.externalId, it.deviceName)
|
||||
}
|
||||
|
||||
mainView.findViewById<TextView>(R.id.add_new_device_title)
|
||||
.setTextColor(AndroidUtils.createPressedColorStateList(app, true, R.color.ctrl_active_light, R.color.ctrl_light))
|
||||
|
||||
mainView.findViewById<ImageView>(R.id.add_new_device_icon)
|
||||
.setImageDrawable(getAddNewDeviceIcon())
|
||||
|
||||
mainView.findViewById<LinearLayout>(R.id.add_new_device_btn).apply {
|
||||
setOnClickListener {
|
||||
fragmentManager?.also { fm ->
|
||||
AddNewDeviceBottomSheet.showInstance(fm, this@SettingsDialogFragment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
container = mainView.findViewById(R.id.osmand_connect_container)
|
||||
for (appConn in TelegramSettings.AppConnect.values()) {
|
||||
val pack = appConn.appPackage
|
||||
|
@ -106,15 +144,6 @@ class SettingsDialogFragment : BaseDialogFragment() {
|
|||
}
|
||||
updateSelectedAppConn()
|
||||
|
||||
container = mainView.findViewById(R.id.share_as_container)
|
||||
val user = telegramHelper.getCurrentUser()
|
||||
if (user != null) {
|
||||
addItemToContainer(inflater, container, user.id.toString(), TelegramUiHelper.getUserName(user))
|
||||
}
|
||||
settings.shareDevicesIds.forEach {
|
||||
addItemToContainer(inflater, container, it.key, it.value)
|
||||
}
|
||||
|
||||
if (user != null) {
|
||||
TelegramUiHelper.setupPhoto(
|
||||
app,
|
||||
|
@ -151,6 +180,19 @@ class SettingsDialogFragment : BaseDialogFragment() {
|
|||
logoutTelegram()
|
||||
dismiss()
|
||||
}
|
||||
AddNewDeviceBottomSheet.NEW_DEVICE_REQUEST_CODE -> {
|
||||
val user = app.telegramHelper.getCurrentUser()
|
||||
if (user != null && data != null) {
|
||||
val deviceName = data.getStringExtra(AddNewDeviceBottomSheet.DEVICE_NAME)
|
||||
val deviceExternalId = data.getStringExtra(AddNewDeviceBottomSheet.DEVICE_EXTERNAL_ID)
|
||||
|
||||
val inflater = activity?.layoutInflater
|
||||
if (inflater != null && deviceName != null && deviceExternalId != null) {
|
||||
addItemToContainer(inflater, shareAsContainer, deviceExternalId, deviceName)
|
||||
Toast.makeText(app, getString(R.string.device_added_successfully, deviceName), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,6 +277,46 @@ class SettingsDialogFragment : BaseDialogFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun updateShareAsDescription() {
|
||||
if (shareAsDescriptionHidden) {
|
||||
shareAsDescription.text = getFullShareAsDescriptionText()
|
||||
} else {
|
||||
shareAsDescription.text = getText(R.string.share_location_as_description)
|
||||
}
|
||||
shareAsDescriptionHidden = !shareAsDescriptionHidden
|
||||
}
|
||||
|
||||
private fun getFullShareAsDescriptionText(): CharSequence {
|
||||
val textHide = "${getString(R.string.shared_string_hide)}."
|
||||
val spannableString = SpannableStringBuilder(getText(R.string.share_location_as_description))
|
||||
val newSpannable = SpannableStringBuilder(getString(R.string.share_location_as_description_second_line, OSMAND_BOT_USERNAME, textHide))
|
||||
|
||||
spannableString.append("\n\n")
|
||||
|
||||
var startIndex = newSpannable.indexOf(OSMAND_BOT_USERNAME)
|
||||
var endIndex = startIndex + OSMAND_BOT_USERNAME.length
|
||||
newSpannable.setSpan(ForegroundColorSpan(app.uiUtils.getActiveColor()), startIndex, endIndex, 0)
|
||||
|
||||
startIndex = newSpannable.indexOf(textHide)
|
||||
endIndex = startIndex + textHide.length
|
||||
newSpannable.setSpan(ForegroundColorSpan(app.uiUtils.getActiveColor()), startIndex, endIndex, 0)
|
||||
|
||||
spannableString.append(newSpannable)
|
||||
|
||||
return spannableString
|
||||
}
|
||||
|
||||
private fun getAddNewDeviceIcon(): Drawable? {
|
||||
val normal = app.uiUtils.getActiveIcon(R.drawable.ic_action_add)
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
val active = app.uiUtils.getIcon(R.drawable.ic_action_add, R.color.ctrl_light)
|
||||
if (normal != null && active != null) {
|
||||
return AndroidUtils.createPressedStateListDrawable(normal, active)
|
||||
}
|
||||
}
|
||||
return normal
|
||||
}
|
||||
|
||||
private fun logoutTelegram() {
|
||||
val act = activity ?: return
|
||||
(act as MainActivity).logoutTelegram()
|
||||
|
|
|
@ -56,7 +56,7 @@ class SharingStatusBottomSheet : DialogFragment() {
|
|||
findViewById<TextView>(R.id.last_location_line).text = sharingStatus.description
|
||||
|
||||
if (sharingStatusType != TelegramSettings.SharingStatusType.INITIALIZING
|
||||
&& sharingStatusType != TelegramSettings.SharingStatusType.SENDING) {
|
||||
&& (sharingStatusType == TelegramSettings.SharingStatusType.SENDING && time != -1L)) {
|
||||
val descriptionTime = when {
|
||||
time > 0 -> OsmandFormatter.getFormattedTime(time, false)
|
||||
sharingStatusType == TelegramSettings.SharingStatusType.NO_GPS -> getString(
|
||||
|
|
|
@ -2,8 +2,14 @@ package net.osmand.telegram.utils
|
|||
|
||||
import android.os.AsyncTask
|
||||
import net.osmand.PlatformUtil
|
||||
import java.io.*
|
||||
import java.net.*
|
||||
import net.osmand.telegram.TelegramApplication
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.BufferedReader
|
||||
import java.io.IOException
|
||||
import java.io.InputStreamReader
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URL
|
||||
|
||||
|
||||
object AndroidNetworkUtils {
|
||||
|
@ -11,21 +17,34 @@ object AndroidNetworkUtils {
|
|||
private val log = PlatformUtil.getLog(AndroidNetworkUtils::class.java)
|
||||
|
||||
interface OnRequestResultListener {
|
||||
fun onResult(result: String)
|
||||
fun onResult(result: String?)
|
||||
}
|
||||
|
||||
fun sendRequestAsync(urlText: String, listener: OnRequestResultListener?) {
|
||||
SendRequestTask(urlText, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
|
||||
fun sendRequestAsync(
|
||||
app: TelegramApplication,
|
||||
urlText: String,
|
||||
json: String?,
|
||||
userOperation: String,
|
||||
toastAllowed: Boolean,
|
||||
post: Boolean,
|
||||
listener: OnRequestResultListener?
|
||||
) {
|
||||
SendRequestTask(app, urlText, json, userOperation, toastAllowed, post, listener).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
|
||||
}
|
||||
|
||||
private class SendRequestTask(
|
||||
private val urlText: String,
|
||||
private val app: TelegramApplication,
|
||||
private val url: String,
|
||||
private val json: String?,
|
||||
private val userOperation: String,
|
||||
private val toastAllowed: Boolean,
|
||||
private val post: Boolean,
|
||||
private val listener: OnRequestResultListener?
|
||||
) : AsyncTask<Void, Void, String?>() {
|
||||
|
||||
override fun doInBackground(vararg params: Void): String? {
|
||||
return try {
|
||||
sendRequest(urlText)
|
||||
sendRequest(app, url, json, userOperation, toastAllowed, post)
|
||||
} catch (e: Exception) {
|
||||
log.error(e.message, e)
|
||||
null
|
||||
|
@ -33,47 +52,99 @@ object AndroidNetworkUtils {
|
|||
}
|
||||
|
||||
override fun onPostExecute(response: String?) {
|
||||
if (response != null) {
|
||||
listener?.onResult(response)
|
||||
}
|
||||
listener?.onResult(response)
|
||||
}
|
||||
}
|
||||
|
||||
fun sendRequest(urlText: String): String? {
|
||||
fun sendRequest(
|
||||
app: TelegramApplication,
|
||||
url: String,
|
||||
jsonBody: String?,
|
||||
userOperation: String,
|
||||
toastAllowed: Boolean,
|
||||
post: Boolean
|
||||
): String? {
|
||||
var connection: HttpURLConnection? = null
|
||||
try {
|
||||
log.info("GET : $urlText")
|
||||
val conn = getHttpURLConnection(urlText)
|
||||
conn.doInput = true
|
||||
conn.doOutput = false
|
||||
conn.requestMethod = "GET"
|
||||
conn.setRequestProperty("User-Agent", "OsmAnd Sharing")
|
||||
log.info("Response code and message : " + conn.responseCode + " " + conn.responseMessage)
|
||||
if (conn.responseCode != 200) {
|
||||
return conn.responseMessage
|
||||
connection = getHttpURLConnection(url)
|
||||
connection.setRequestProperty("Accept-Charset", "UTF-8")
|
||||
connection.setRequestProperty("User-Agent", app.packageName)
|
||||
connection.connectTimeout = 15000
|
||||
if (jsonBody != null && post) {
|
||||
connection.doInput = true
|
||||
connection.doOutput = true
|
||||
connection.useCaches = false
|
||||
connection.requestMethod = "POST"
|
||||
|
||||
connection.setRequestProperty("Accept", "application/json")
|
||||
connection.setRequestProperty("Content-Type", "application/json")
|
||||
connection.setRequestProperty("Content-Length", jsonBody.toByteArray(charset("UTF-8")).size.toString())
|
||||
|
||||
connection.setFixedLengthStreamingMode(jsonBody.toByteArray(charset("UTF-8")).size)
|
||||
|
||||
val output = BufferedOutputStream(connection.outputStream)
|
||||
|
||||
output.write(jsonBody.toByteArray(charset("UTF-8")))
|
||||
output.flush()
|
||||
output.close()
|
||||
|
||||
} else {
|
||||
connection.requestMethod = "GET"
|
||||
connection.connect()
|
||||
}
|
||||
val inputStream = conn.inputStream
|
||||
val responseBody = StringBuilder()
|
||||
responseBody.setLength(0)
|
||||
if (inputStream != null) {
|
||||
val bufferedInput = BufferedReader(InputStreamReader(inputStream, "UTF-8"))
|
||||
var s = bufferedInput.readLine()
|
||||
var first = true
|
||||
while (s != null) {
|
||||
if (first) {
|
||||
first = false
|
||||
} else {
|
||||
responseBody.append("\n")
|
||||
}
|
||||
responseBody.append(s)
|
||||
s = bufferedInput.readLine()
|
||||
|
||||
if (connection.responseCode != HttpURLConnection.HTTP_OK) {
|
||||
if (toastAllowed) {
|
||||
val msg = (userOperation + " " + "Failed: " + connection.responseMessage)
|
||||
log.error(msg)
|
||||
}
|
||||
inputStream.close()
|
||||
} else {
|
||||
val responseBody = StringBuilder()
|
||||
responseBody.setLength(0)
|
||||
val i = connection.inputStream
|
||||
if (i != null) {
|
||||
val input = BufferedReader(InputStreamReader(i, "UTF-8"), 256)
|
||||
var s: String? = input.readLine()
|
||||
var f = true
|
||||
while (s != null) {
|
||||
if (!f) {
|
||||
responseBody.append("\n")
|
||||
} else {
|
||||
f = false
|
||||
}
|
||||
responseBody.append(s)
|
||||
s = input.readLine()
|
||||
}
|
||||
try {
|
||||
input.close()
|
||||
i.close()
|
||||
} catch (e: Exception) {
|
||||
// ignore exception
|
||||
}
|
||||
|
||||
}
|
||||
return responseBody.toString()
|
||||
}
|
||||
} catch (e: NullPointerException) {
|
||||
if (toastAllowed) {
|
||||
val msg = (userOperation + " " + "Failed - $e" + ": " + connection?.responseMessage)
|
||||
log.error(msg)
|
||||
}
|
||||
} catch (e: MalformedURLException) {
|
||||
if (toastAllowed) {
|
||||
val msg = (userOperation + " " + "Failed - $e" + ": " + connection?.responseMessage)
|
||||
log.error(msg)
|
||||
}
|
||||
return responseBody.toString()
|
||||
} catch (e: IOException) {
|
||||
log.error(e.message, e)
|
||||
return e.message
|
||||
if (toastAllowed) {
|
||||
val msg = (userOperation + " " + "Failed - $e" + ": " + connection?.responseMessage)
|
||||
log.error(msg)
|
||||
}
|
||||
} finally {
|
||||
connection?.disconnect()
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
@Throws(MalformedURLException::class, IOException::class)
|
||||
|
|
|
@ -6,16 +6,21 @@ import android.content.ContentResolver
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.ColorStateList
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Color
|
||||
import android.graphics.Paint
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.StateListDrawable
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.support.annotation.AttrRes
|
||||
import android.support.annotation.ColorInt
|
||||
import android.support.annotation.ColorRes
|
||||
import android.support.v4.app.ActivityCompat
|
||||
import android.support.v4.app.DialogFragment
|
||||
import android.support.v4.app.FragmentManager
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v4.content.FileProvider
|
||||
import android.util.TypedValue
|
||||
import android.util.TypedValue.COMPLEX_UNIT_DIP
|
||||
|
@ -131,6 +136,46 @@ object AndroidUtils {
|
|||
return ctx.resources.getDimensionPixelSize(R.dimen.list_popup_window_height)
|
||||
}
|
||||
|
||||
fun createPressedColorStateList(
|
||||
ctx: Context, light: Boolean,
|
||||
@ColorRes lightNormal: Int, @ColorRes lightPressed: Int,
|
||||
@ColorRes darkNormal: Int = 0, @ColorRes darkPressed: Int = 0
|
||||
): ColorStateList {
|
||||
return createColorStateList(
|
||||
ctx, light, android.R.attr.state_pressed,
|
||||
lightNormal, lightPressed, darkNormal, darkPressed
|
||||
)
|
||||
}
|
||||
|
||||
fun createColorStateList(
|
||||
ctx: Context, light: Boolean, state: Int,
|
||||
@ColorRes lightNormal: Int, @ColorRes lightState: Int,
|
||||
@ColorRes darkNormal: Int, @ColorRes darkState: Int
|
||||
): ColorStateList {
|
||||
return ColorStateList(
|
||||
arrayOf(intArrayOf(state), intArrayOf()),
|
||||
intArrayOf(
|
||||
ContextCompat.getColor(ctx, if (light) lightState else darkState),
|
||||
ContextCompat.getColor(ctx, if (light) lightNormal else darkNormal)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun createPressedStateListDrawable(normal: Drawable, pressed: Drawable): StateListDrawable {
|
||||
return createStateListDrawable(normal, pressed, android.R.attr.state_pressed)
|
||||
}
|
||||
|
||||
fun createStateListDrawable(
|
||||
normal: Drawable,
|
||||
stateDrawable: Drawable,
|
||||
state: Int
|
||||
): StateListDrawable {
|
||||
val res = StateListDrawable()
|
||||
res.addState(intArrayOf(state), stateDrawable)
|
||||
res.addState(intArrayOf(), normal)
|
||||
return res
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
fun getAttrColor(ctx: Context, @AttrRes attrId: Int, @ColorInt defaultColor: Int = 0): Int {
|
||||
val ta = ctx.theme.obtainStyledAttributes(intArrayOf(attrId))
|
||||
|
|
|
@ -1,46 +1,95 @@
|
|||
package net.osmand.telegram.utils
|
||||
|
||||
import net.osmand.PlatformUtil
|
||||
import net.osmand.telegram.SHARE_DEVICES_KEY
|
||||
import net.osmand.telegram.TelegramApplication
|
||||
import net.osmand.telegram.TelegramSettings
|
||||
import org.drinkless.td.libcore.telegram.TdApi
|
||||
import org.json.JSONException
|
||||
import org.json.JSONObject
|
||||
|
||||
const val BASE_URL = "https://live.osmand.net"
|
||||
|
||||
object OsmandApiUtils {
|
||||
|
||||
private val log = PlatformUtil.getLog(OsmandApiUtils::class.java)
|
||||
|
||||
fun updateSharingDevices(app: TelegramApplication, userId: Int) {
|
||||
AndroidNetworkUtils.sendRequestAsync(
|
||||
"https://osmand.net/device/send-devices?uid=$userId",
|
||||
AndroidNetworkUtils.sendRequestAsync(app, "$BASE_URL/device/send-devices?uid=$userId", null, "Get Devices", true, false,
|
||||
object : AndroidNetworkUtils.OnRequestResultListener {
|
||||
override fun onResult(result: String) {
|
||||
val list = parseJsonContents(result)
|
||||
app.settings.updateShareDevicesIds(list)
|
||||
override fun onResult(result: String?) {
|
||||
if (result != null) {
|
||||
val list = parseJsonContents(result)
|
||||
app.settings.updateShareDevicesIds(list)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun createNewDevice(
|
||||
app: TelegramApplication,
|
||||
user: TdApi.User,
|
||||
isBot: Boolean,
|
||||
deviceName: String,
|
||||
chatId: Long,
|
||||
listener: AndroidNetworkUtils.OnRequestResultListener
|
||||
) {
|
||||
val json = getNewDeviceJson(user, isBot, deviceName, chatId)
|
||||
if (json != null) {
|
||||
AndroidNetworkUtils.sendRequestAsync(app, "$BASE_URL/device/new", json.toString(), "add Device", true, true, listener)
|
||||
}
|
||||
}
|
||||
|
||||
fun parseDeviceBot(deviceJSON: JSONObject): TelegramSettings.DeviceBot? {
|
||||
return try {
|
||||
TelegramSettings.DeviceBot().apply {
|
||||
id = deviceJSON.optLong(TelegramSettings.DeviceBot.DEVICE_ID)
|
||||
userId = deviceJSON.optLong(TelegramSettings.DeviceBot.USER_ID)
|
||||
chatId = deviceJSON.optLong(TelegramSettings.DeviceBot.CHAT_ID)
|
||||
deviceName = deviceJSON.optString(TelegramSettings.DeviceBot.DEVICE_NAME)
|
||||
externalId = deviceJSON.optString(TelegramSettings.DeviceBot.EXTERNAL_ID)
|
||||
data = deviceJSON.optString(TelegramSettings.DeviceBot.DATA)
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
log.error(e.message, e)
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun parseJsonContents(contentsJson: String): List<TelegramSettings.DeviceBot> {
|
||||
val list = mutableListOf<TelegramSettings.DeviceBot>()
|
||||
try {
|
||||
val jArray = JSONObject(contentsJson).getJSONArray("devices")
|
||||
val jArray = JSONObject(contentsJson).getJSONArray(SHARE_DEVICES_KEY)
|
||||
for (i in 0 until jArray.length()) {
|
||||
val deviceJSON = jArray.getJSONObject(i)
|
||||
val deviceBot = TelegramSettings.DeviceBot().apply {
|
||||
id = deviceJSON.getLong("id")
|
||||
userId = deviceJSON.getLong("userId")
|
||||
chatId = deviceJSON.getLong("chatId")
|
||||
deviceName = deviceJSON.getString("deviceName")
|
||||
externalId = deviceJSON.getString("externalId")
|
||||
data = deviceJSON.getString("data")
|
||||
val deviceBot = parseDeviceBot(deviceJSON)
|
||||
if (deviceBot != null) {
|
||||
list.add(deviceBot)
|
||||
}
|
||||
list.add(deviceBot)
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
log.error(e.message, e)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
private fun getNewDeviceJson(user: TdApi.User, isBot: Boolean, deviceName: String, chatId: Long): JSONObject? {
|
||||
return try {
|
||||
val json = JSONObject()
|
||||
json.put("deviceName", deviceName)
|
||||
json.put("chatId", chatId)
|
||||
val jsonUser = JSONObject()
|
||||
jsonUser.put("id", user.id)
|
||||
jsonUser.put("firstName", user.firstName)
|
||||
jsonUser.put("isBot", isBot)
|
||||
jsonUser.put("lastName", user.lastName)
|
||||
jsonUser.put("userName", user.username)
|
||||
jsonUser.put("languageCode", user.languageCode)
|
||||
json.put("user", jsonUser)
|
||||
} catch (e: JSONException) {
|
||||
log.error(e)
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue