Add notification rate limit info to settings (#1015)

* Add notification rate limit to settings

* Clean up

* Allow the preference to be copied

* Move logic to integrationService, make summary look better

* Review comments

* Clean up

* Lint
This commit is contained in:
Daniel Shokouhi 2020-10-08 11:05:13 -07:00 committed by GitHub
parent 989229f2d8
commit 08456d2a1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 108 additions and 0 deletions

View file

@ -127,6 +127,18 @@ class SettingsFragment : PreferenceFragmentCompat(), SettingsView {
return@setOnPreferenceClickListener true
}
if (BuildConfig.FLAVOR == "full") {
findPreference<Preference>("notification_rate_limit")?.let {
val rateLimits = presenter.getNotificationRateLimits()
if (rateLimits != null)
it.isVisible = true
it.summary = "\nSuccessful: ${rateLimits?.successful} Errors: ${rateLimits?.errors}" +
"\n\nRemaining/Maximum: ${rateLimits?.remaining}/${rateLimits?.maximum}" +
"\n\nResets at: ${rateLimits?.resetsAt}"
}
}
findPreference<Preference>("changelog")?.let {
val link = if (BuildConfig.VERSION_NAME.startsWith("LOCAL"))
"https://github.com/home-assistant/android/releases"

View file

@ -1,6 +1,7 @@
package io.homeassistant.companion.android.settings
import androidx.preference.PreferenceDataStore
import io.homeassistant.companion.android.common.data.integration.impl.entities.RateLimitResponse
interface SettingsPresenter {
fun getPreferenceDataStore(): PreferenceDataStore
@ -9,6 +10,7 @@ interface SettingsPresenter {
fun nfcEnabled(): Boolean
fun isLockEnabled(): Boolean
fun sessionTimeOut(): Int
fun getNotificationRateLimits(): RateLimitResponse?
fun setSessionExpireMillis(value: Long)
fun getSessionExpireMillis(): Long

View file

@ -5,6 +5,7 @@ import androidx.preference.PreferenceDataStore
import io.homeassistant.companion.android.common.data.authentication.AuthenticationRepository
import io.homeassistant.companion.android.common.data.integration.DeviceRegistration
import io.homeassistant.companion.android.common.data.integration.IntegrationRepository
import io.homeassistant.companion.android.common.data.integration.impl.entities.RateLimitResponse
import io.homeassistant.companion.android.common.data.url.UrlRepository
import io.homeassistant.companion.android.themes.ThemesManager
import javax.inject.Inject
@ -188,4 +189,15 @@ class SettingsPresenterImpl @Inject constructor(
(Integer.parseInt(splitVersion[0]) > 0 || Integer.parseInt(splitVersion[1]) >= 114)
}
}
override fun getNotificationRateLimits(): RateLimitResponse? {
return runBlocking {
try {
integrationUseCase.getNotificationRateLimits()
} catch (e: Exception) {
Log.d(TAG, "Unable to get rate limits")
return@runBlocking null
}
}
}
}

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="@color/colorAccent"
android:pathData="M18,17v-6c0,-3.07 -1.63,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5S10.5,3.17 10.5,4v0.68C7.64,5.36 6,7.92 6,11v6H4v2h10h0.38H20v-2H18zM16,17H8v-6c0,-2.48 1.51,-4.5 4,-4.5s4,2.02 4,4.5V17z"/>
<path
android:fillColor="@color/colorAccent"
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4C10,21.1 10.9,22 12,22z"/>
</vector>

View file

@ -141,6 +141,8 @@ Home Assistant instance</string>
<string name="need_help">Need Help?</string>
<string name="notification_dismiss_failure">Failed to send event on notification dismissed</string>
<string name="nfc_btn_create_duplicate">Create duplicate</string>
<string name="rate_limit_title">Notification Rate Limit</string>
<string name="rate_limit_summary">Rate limit data</string>
<string name="nfc_btn_fire_event">Fire event</string>
<string name="nfc_btn_read_tag">Read NFC Tag</string>
<string name="nfc_btn_share">Share</string>

View file

@ -87,6 +87,13 @@
</PreferenceCategory>
<PreferenceCategory
android:title="@string/app_version_info">
<Preference
android:key="notification_rate_limit"
android:title="@string/rate_limit_title"
app:isPreferenceVisible="false"
app:enableCopying="true"
android:icon="@drawable/ic_notifications"
android:summary="@string/rate_limit_summary"/>
<Preference
android:key="changelog"
android:icon="@drawable/ic_changelog"

View file

@ -1,5 +1,7 @@
package io.homeassistant.companion.android.common.data.integration
import io.homeassistant.companion.android.common.data.integration.impl.entities.RateLimitResponse
interface IntegrationRepository {
suspend fun registerDevice(deviceRegistration: DeviceRegistration)
@ -8,6 +10,7 @@ interface IntegrationRepository {
suspend fun isRegistered(): Boolean
suspend fun getNotificationRateLimits(): RateLimitResponse
suspend fun renderTemplate(template: String, variables: Map<String, String>): String
suspend fun updateLocation(updateLocation: UpdateLocation)

View file

@ -1,5 +1,6 @@
package io.homeassistant.companion.android.common.data.integration.impl
import android.util.Log
import io.homeassistant.companion.android.common.data.LocalStorage
import io.homeassistant.companion.android.common.data.authentication.AuthenticationRepository
import io.homeassistant.companion.android.common.data.integration.DeviceRegistration
@ -15,6 +16,8 @@ import io.homeassistant.companion.android.common.data.integration.impl.entities.
import io.homeassistant.companion.android.common.data.integration.impl.entities.FireEventRequest
import io.homeassistant.companion.android.common.data.integration.impl.entities.GetConfigResponse
import io.homeassistant.companion.android.common.data.integration.impl.entities.IntegrationRequest
import io.homeassistant.companion.android.common.data.integration.impl.entities.RateLimitRequest
import io.homeassistant.companion.android.common.data.integration.impl.entities.RateLimitResponse
import io.homeassistant.companion.android.common.data.integration.impl.entities.RegisterDeviceRequest
import io.homeassistant.companion.android.common.data.integration.impl.entities.SensorRequest
import io.homeassistant.companion.android.common.data.integration.impl.entities.ServiceCallRequest
@ -23,6 +26,7 @@ import io.homeassistant.companion.android.common.data.integration.impl.entities.
import io.homeassistant.companion.android.common.data.url.UrlRepository
import javax.inject.Inject
import javax.inject.Named
import kotlin.Exception
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
class IntegrationRepositoryImpl @Inject constructor(
@ -52,6 +56,8 @@ class IntegrationRepositoryImpl @Inject constructor(
private const val PREF_SESSION_TIMEOUT = "session_timeout"
private const val PREF_SESSION_EXPIRE = "session_expire"
private const val PREF_SENSORS_REGISTERED = "sensors_registered"
private const val TAG = "IntegrationRepository"
private const val RATE_LIMIT_URL = "https://mobile-apps.home-assistant.io/api/checkRateLimits"
}
override suspend fun registerDevice(deviceRegistration: DeviceRegistration) {
@ -301,6 +307,22 @@ class IntegrationRepositoryImpl @Inject constructor(
return localStorage.getLong(PREF_SESSION_EXPIRE) ?: 0
}
override suspend fun getNotificationRateLimits(): RateLimitResponse {
val pushToken = localStorage.getString(PREF_PUSH_TOKEN) ?: ""
val requestBody = RateLimitRequest(pushToken)
var checkRateLimits: RateLimitResponse? = null
try {
checkRateLimits = integrationService.getRateLimit(RATE_LIMIT_URL, requestBody).rateLimits
} catch (e: Exception) {
Log.e(TAG, "Unable to get notification rate limits", e)
}
if (checkRateLimits != null)
return checkRateLimits
throw IntegrationException()
}
override suspend fun getThemeColor(): String {
val getConfigRequest =
IntegrationRequest(

View file

@ -2,11 +2,13 @@ package io.homeassistant.companion.android.common.data.integration.impl
import io.homeassistant.companion.android.common.data.integration.Panel
import io.homeassistant.companion.android.common.data.integration.ZoneAttributes
import io.homeassistant.companion.android.common.data.integration.impl.entities.CheckRateLimits
import io.homeassistant.companion.android.common.data.integration.impl.entities.DiscoveryInfoResponse
import io.homeassistant.companion.android.common.data.integration.impl.entities.DomainResponse
import io.homeassistant.companion.android.common.data.integration.impl.entities.EntityResponse
import io.homeassistant.companion.android.common.data.integration.impl.entities.GetConfigResponse
import io.homeassistant.companion.android.common.data.integration.impl.entities.IntegrationRequest
import io.homeassistant.companion.android.common.data.integration.impl.entities.RateLimitRequest
import io.homeassistant.companion.android.common.data.integration.impl.entities.RegisterDeviceRequest
import io.homeassistant.companion.android.common.data.integration.impl.entities.RegisterDeviceResponse
import okhttp3.HttpUrl
@ -71,6 +73,12 @@ interface IntegrationService {
@Body request: IntegrationRequest
): Array<Panel>
@POST
suspend fun getRateLimit(
@Url url: String,
@Body request: RateLimitRequest
): CheckRateLimits
@POST
suspend fun updateSensors(
@Url url: HttpUrl,

View file

@ -0,0 +1,9 @@
package io.homeassistant.companion.android.common.data.integration.impl.entities
import com.fasterxml.jackson.annotation.JsonProperty
data class CheckRateLimits(
var target: String,
@JsonProperty("rateLimits")
var rateLimits: RateLimitResponse
)

View file

@ -0,0 +1,5 @@
package io.homeassistant.companion.android.common.data.integration.impl.entities
data class RateLimitRequest(
val push_token: String
)

View file

@ -0,0 +1,14 @@
package io.homeassistant.companion.android.common.data.integration.impl.entities
import com.fasterxml.jackson.annotation.JsonProperty
data class RateLimitResponse(
var attempts: Int,
var successful: Int,
var errors: Int,
var total: Int,
var maximum: Int,
var remaining: Int,
@JsonProperty("resetsAt")
var resetsAt: String
)