Merge pull request #6195 from osmandapp/TelegramSettingsImprovements

Add BatteryOptimization dialog and improve UI in settings
This commit is contained in:
Alexander Sytnyk 2018-10-19 16:41:44 +03:00 committed by GitHub
commit 33c81b34dd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 255 additions and 21 deletions

View file

@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<application
android:name="net.osmand.telegram.TelegramApplication"

View file

@ -0,0 +1,85 @@
<?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/sharing_in_background"
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/battery_optimization_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" />
</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" />
<include
layout="@layout/primary_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
</LinearLayout>

View file

@ -200,8 +200,8 @@
<ImageView
android:id="@+id/user_icon"
android:layout_width="@dimen/list_item_icon_size"
android:layout_height="@dimen/list_item_icon_size"
android:layout_width="@dimen/list_item_icon_size_big"
android:layout_height="@dimen/list_item_icon_size_big"
android:layout_marginEnd="@dimen/content_padding_standard"
android:layout_marginLeft="@dimen/content_padding_half"
android:layout_marginRight="@dimen/content_padding_standard"

View file

@ -14,8 +14,8 @@
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_width="@dimen/list_item_icon_size"
android:layout_height="@dimen/list_item_icon_size"
android:layout_marginEnd="@dimen/content_padding_big"
android:layout_marginRight="@dimen/content_padding_big"
tools:src="@drawable/ic_action_live_now"

View file

@ -26,8 +26,8 @@
<ImageView
android:id="@+id/icon"
android:layout_width="@dimen/list_item_icon_size"
android:layout_height="@dimen/list_item_icon_size"
android:layout_width="@dimen/list_item_icon_size_big"
android:layout_height="@dimen/list_item_icon_size_big"
android:layout_marginEnd="@dimen/list_item_icon_margin_right"
android:layout_marginLeft="@dimen/list_item_icon_margin_left"
android:layout_marginRight="@dimen/list_item_icon_margin_right"

View file

@ -21,8 +21,8 @@
<ImageView
android:id="@+id/icon"
android:layout_width="@dimen/list_item_icon_size"
android:layout_height="@dimen/list_item_icon_size"
android:layout_width="@dimen/list_item_icon_size_big"
android:layout_height="@dimen/list_item_icon_size_big"
android:layout_marginLeft="@dimen/list_item_icon_margin_left"
android:layout_marginRight="@dimen/list_item_icon_margin_left"
tools:src="@drawable/img_user_picture" />

View file

@ -22,8 +22,8 @@
<ImageView
android:id="@+id/icon"
android:layout_width="@dimen/list_item_icon_size"
android:layout_height="@dimen/list_item_icon_size"
android:layout_width="@dimen/list_item_icon_size_big"
android:layout_height="@dimen/list_item_icon_size_big"
android:layout_marginEnd="@dimen/list_item_icon_margin_right"
android:layout_marginLeft="@dimen/list_item_icon_margin_left"
android:layout_marginRight="@dimen/list_item_icon_margin_right"

View file

@ -30,7 +30,8 @@
<dimen name="list_item_height_big">64dp</dimen>
<dimen name="list_item_icon_size_small">14dp</dimen>
<dimen name="list_item_icon_size">40dp</dimen>
<dimen name="list_item_icon_size">24dp</dimen>
<dimen name="list_item_icon_size_big">40dp</dimen>
<dimen name="list_item_icon_margin_left">12dp</dimen>
<dimen name="list_item_icon_margin_right">20dp</dimen>

View file

@ -1,4 +1,10 @@
<resources>
<string name="background_work_description">Change battery optimization settings, for stable location sharing</string>
<string name="background_work">Background work</string>
<string name="battery_optimization_description">For stable sharing of your position in the background, it is advisable to disable battery optimization for OsmAnd Telegram.\n\nIf optimization is enabled, the system may automatically turn off the application running in the background (when the screen is locked and/or the app is minimized). This happens without notification and causes the geo position broadcast to stop.</string>
<string name="sharing_in_background">Sharing in the background</string>
<string name="go_to_settings">Go to settings</string>
<string name="shared_string_later">Later</string>
<string name="not_sent_yet">Not sent yet</string>
<string name="not_found_yet">Not found yet</string>
<string name="re_send_location">Re-send location</string>

View file

@ -67,6 +67,8 @@ private const val LIVE_NOW_SORT_TYPE_KEY = "live_now_sort_type"
private const val SHARE_CHATS_INFO_KEY = "share_chats_info"
private const val BATTERY_OPTIMISATION_ASKED = "battery_optimisation_asked"
class TelegramSettings(private val app: TelegramApplication) {
private var shareChatsInfo = ConcurrentHashMap<Long, ShareChatInfo>()
@ -91,6 +93,8 @@ class TelegramSettings(private val app: TelegramApplication) {
val gpsAndLocPrefs = listOf(SendMyLocPref(), StaleLocPref(), LocHistoryPref())
var batteryOptimisationAsked = false
init {
updatePrefs()
read()
@ -208,7 +212,7 @@ class TelegramSettings(private val app: TelegramApplication) {
SharingStatusType.NO_GPS
} else {
var sendChatsErrors = false
shareChatsInfo.forEach { _, shareInfo ->
shareChatsInfo.forEach { (_, shareInfo) ->
if (shareInfo.hasSharingError || shareInfo.lastSuccessfulSendTimeMs == -1L) {
sendChatsErrors = true
locationTime = shareInfo.lastSuccessfulSendTimeMs
@ -274,6 +278,8 @@ class TelegramSettings(private val app: TelegramApplication) {
edit.putString(LIVE_NOW_SORT_TYPE_KEY, liveNowSortType.name)
edit.putBoolean(BATTERY_OPTIMISATION_ASKED, batteryOptimisationAsked)
try {
val jArray = JSONArray()
shareChatsInfo.forEach { (chatId, chatInfo) ->
@ -332,6 +338,8 @@ class TelegramSettings(private val app: TelegramApplication) {
liveNowSortType = LiveNowSortType.valueOf(
prefs.getString(LIVE_NOW_SORT_TYPE_KEY, LiveNowSortType.SORT_BY_GROUP.name)
)
batteryOptimisationAsked = prefs.getBoolean(BATTERY_OPTIMISATION_ASKED,false)
}
private fun parseShareChatsInfo(json: JSONArray) {

View file

@ -335,12 +335,10 @@ class TelegramHelper private constructor() {
}
}
fun getUserGreyPhotoPath(user: TdApi.User): String? {
return if (hasGrayscaleUserPhoto(user.id)) {
"$appDir/$GRAYSCALE_PHOTOS_DIR${user.id}$GRAYSCALE_PHOTOS_EXT"
} else {
null
}
fun getUserGreyPhotoPath(user: TdApi.User?) = when {
user == null -> null
hasGrayscaleUserPhoto(user.id) -> "$appDir/$GRAYSCALE_PHOTOS_DIR${user.id}$GRAYSCALE_PHOTOS_EXT"
else -> null
}
fun getOsmAndBotDeviceName(message: TdApi.Message): String {

View file

@ -0,0 +1,91 @@
package net.osmand.telegram.ui
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.PowerManager
import android.provider.Settings
import android.support.design.widget.BottomSheetBehavior
import android.support.v4.app.DialogFragment
import android.support.v4.app.FragmentManager
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import net.osmand.PlatformUtil
import net.osmand.telegram.R
import net.osmand.telegram.TelegramApplication
import net.osmand.telegram.ui.views.BottomSheetDialog
class BatteryOptimizationBottomSheet : DialogFragment() {
private val app: TelegramApplication
get() = activity?.application as TelegramApplication
private val log = PlatformUtil.getLog(BatteryOptimizationBottomSheet::class.java)
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_battery_optimization, 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) {}
})
mainView.findViewById<TextView>(R.id.secondary_btn).apply {
setText(R.string.shared_string_later)
setOnClickListener { dismiss() }
}
mainView.findViewById<TextView>(R.id.primary_btn).apply {
setText(R.string.go_to_settings)
setOnClickListener {
if (Build.VERSION.SDK_INT >= 26) {
val pkg = app.packageName
val pm = app.getSystemService(PowerManager::class.java)
if (pm != null) {
val intent = if (!pm.isIgnoringBatteryOptimizations(pkg)) {
Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).setData(Uri.parse("package:$pkg"))
} else {
Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS)
}
if (intent.resolveActivity(app.packageManager) != null) {
startActivity(intent)
} else {
log.error("No Intent available to handle action")
}
}
}
dismiss()
}
}
return mainView
}
companion object {
private const val TAG = "BatteryOptimizationBottomSheet"
fun showInstance(fm: FragmentManager): Boolean {
return try {
BatteryOptimizationBottomSheet().show(fm, TAG)
true
} catch (e: RuntimeException) {
false
}
}
}
}

View file

@ -245,6 +245,12 @@ class MyLocationTabFragment : Fragment(), TelegramListener {
sharingMode = settings.hasAnyChatToShareLocation()
clearSelection()
updateContent()
if (sharingMode && !settings.batteryOptimisationAsked && Build.VERSION.SDK_INT >= 26) {
fragmentManager?.also { fm ->
BatteryOptimizationBottomSheet.showInstance(fm)
settings.batteryOptimisationAsked = true
}
}
}
DisableSharingBottomSheet.SHARING_DISABLED_REQUEST_CODE -> {
sharingMode = false

View file

@ -1,6 +1,7 @@
package net.osmand.telegram.ui
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.support.v4.app.FragmentManager
import android.support.v7.widget.ListPopupWindow
@ -15,6 +16,7 @@ import net.osmand.telegram.TelegramSettings
import net.osmand.telegram.TelegramSettings.DurationPref
import net.osmand.telegram.helpers.TelegramUiHelper
import net.osmand.telegram.utils.AndroidUtils
import org.drinkless.td.libcore.telegram.TdApi
class SettingsDialogFragment : BaseDialogFragment() {
@ -50,6 +52,19 @@ class SettingsDialogFragment : BaseDialogFragment() {
}
}
if (Build.VERSION.SDK_INT >= 26) {
inflater.inflate(R.layout.item_with_desc_and_right_value, container, false).apply {
findViewById<ImageView>(R.id.icon).setImageDrawable(uiUtils.getThemedIcon(R.drawable.ic_action_background_work))
findViewById<TextView>(R.id.title).text = getText(R.string.background_work)
findViewById<TextView>(R.id.description).text = getText(R.string.background_work_description)
findViewById<TextView>(R.id.value).visibility = View.GONE
setOnClickListener {
fragmentManager?.also { BatteryOptimizationBottomSheet.showInstance(it) }
}
container.addView(this)
}
}
container = mainView.findViewById(R.id.osmand_connect_container)
for (appConn in TelegramSettings.AppConnect.values()) {
val pack = appConn.appPackage
@ -141,11 +156,15 @@ class SettingsDialogFragment : BaseDialogFragment() {
private fun addItemToContainer(inflater: LayoutInflater, container: ViewGroup, tag: String, title: String) {
inflater.inflate(R.layout.item_with_rb_and_btn, container, false).apply {
val checked = tag == settings.currentSharingMode
setupSharingModeIcon(this, checked, telegramHelper.getCurrentUser(), tag)
findViewById<TextView>(R.id.title).text = title
findViewById<View>(R.id.primary_btn).visibility = View.GONE
findViewById<RadioButton>(R.id.radio_button).apply {
visibility = View.VISIBLE
isChecked = tag == settings.currentSharingMode
isChecked = checked
}
setOnClickListener {
settings.currentSharingMode = tag
@ -186,12 +205,31 @@ class SettingsDialogFragment : BaseDialogFragment() {
}
}
private fun setupSharingModeIcon(view: View, checked: Boolean, user: TdApi.User?, tag: String) {
if (tag == user?.id.toString()) {
val path = if (checked) {
telegramHelper.getUserPhotoPath(user)
} else {
telegramHelper.getUserGreyPhotoPath(user)
}
TelegramUiHelper.setupPhoto(app, view.findViewById<ImageView>(R.id.icon), path, R.drawable.img_user_picture, false)
} else {
val icon = if (checked) {
uiUtils.getActiveIcon(R.drawable.ic_device_picture)
} else {
uiUtils.getThemedIcon(R.drawable.ic_device_picture)
}
view.findViewById<ImageView>(R.id.icon).setImageDrawable(icon)
}
}
private fun updateSelectedSharingMode() {
view?.findViewById<ViewGroup>(R.id.share_as_container)?.apply {
for (i in 0 until childCount) {
getChildAt(i).apply {
findViewById<RadioButton>(R.id.radio_button).isChecked =
tag == settings.currentSharingMode
val checked = tag == app.settings.currentSharingMode
setupSharingModeIcon(this, checked, telegramHelper.getCurrentUser(), tag.toString())
findViewById<RadioButton>(R.id.radio_button).isChecked = checked
}
}
}