ntfy-android/app/src/main/java/io/heckel/ntfy/ui/DetailSettingsActivity.kt

520 lines
26 KiB
Kotlin
Raw Normal View History

2022-01-31 08:05:36 +13:00
package io.heckel.ntfy.ui
2022-05-09 12:41:17 +12:00
import android.content.ContentResolver
2022-07-02 15:30:30 +12:00
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
2022-05-07 13:03:15 +12:00
import android.net.Uri
2022-01-31 08:05:36 +13:00
import android.os.Bundle
import android.provider.Settings
import android.text.TextUtils
2022-05-09 12:41:17 +12:00
import android.widget.Toast
2022-05-07 13:03:15 +12:00
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
2022-01-31 08:05:36 +13:00
import androidx.appcompat.app.AppCompatActivity
2022-05-07 13:03:15 +12:00
import androidx.core.content.FileProvider
2022-05-09 08:04:52 +12:00
import androidx.core.graphics.drawable.toDrawable
2022-01-31 08:05:36 +13:00
import androidx.lifecycle.lifecycleScope
2022-05-06 13:06:21 +12:00
import androidx.preference.*
2022-07-02 15:30:30 +12:00
import androidx.preference.Preference.OnPreferenceClickListener
2022-05-06 13:06:21 +12:00
import io.heckel.ntfy.BuildConfig
2022-01-31 08:05:36 +13:00
import io.heckel.ntfy.R
import io.heckel.ntfy.db.Repository
import io.heckel.ntfy.db.Subscription
2022-07-17 08:32:09 +12:00
import io.heckel.ntfy.msg.DownloadAttachmentWorker
import io.heckel.ntfy.msg.NotificationService
2022-01-31 08:05:36 +13:00
import io.heckel.ntfy.service.SubscriberServiceManager
2022-05-06 13:06:21 +12:00
import io.heckel.ntfy.util.*
import kotlinx.coroutines.*
2022-05-07 13:03:15 +12:00
import java.io.File
import java.io.IOException
2022-05-06 08:56:06 +12:00
import java.util.*
2022-01-31 08:05:36 +13:00
/**
* Subscription settings
*/
class DetailSettingsActivity : AppCompatActivity() {
private lateinit var repository: Repository
private lateinit var serviceManager: SubscriberServiceManager
private lateinit var settingsFragment: SettingsFragment
private lateinit var notificationService: NotificationService
private var subscriptionId: Long = 0
2022-01-31 08:05:36 +13:00
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)
Log.d(TAG, "Create $this")
repository = Repository.getInstance(this)
serviceManager = SubscriberServiceManager(this)
notificationService = NotificationService(this)
subscriptionId = intent.getLongExtra(DetailActivity.EXTRA_SUBSCRIPTION_ID, 0)
2022-01-31 08:05:36 +13:00
if (savedInstanceState == null) {
settingsFragment = SettingsFragment() // Empty constructor!
settingsFragment.arguments = Bundle().apply {
this.putLong(DetailActivity.EXTRA_SUBSCRIPTION_ID, subscriptionId)
}
2022-01-31 08:05:36 +13:00
supportFragmentManager
.beginTransaction()
.replace(R.id.settings_layout, settingsFragment)
.commit()
}
2022-05-06 08:56:06 +12:00
// Title
val displayName = intent.getStringExtra(DetailActivity.EXTRA_SUBSCRIPTION_DISPLAY_NAME) ?: return
title = displayName
2022-01-31 08:05:36 +13:00
// Show 'Back' button
supportActionBar?.setDisplayHomeAsUpEnabled(true)
}
override fun onSupportNavigateUp(): Boolean {
finish() // Return to previous activity when nav "back" is pressed!
return true
}
2022-01-31 08:05:36 +13:00
class SettingsFragment : PreferenceFragmentCompat() {
2022-05-09 12:41:17 +12:00
private lateinit var resolver: ContentResolver
2022-01-31 08:05:36 +13:00
private lateinit var repository: Repository
private lateinit var serviceManager: SubscriberServiceManager
private lateinit var notificationService: NotificationService
2022-05-06 08:56:06 +12:00
private lateinit var subscription: Subscription
2022-05-09 08:04:52 +12:00
private lateinit var iconSetPref: Preference
private lateinit var openChannelsPref: Preference
2022-05-09 08:04:52 +12:00
private lateinit var iconSetLauncher: ActivityResultLauncher<String>
private lateinit var iconRemovePref: Preference
2022-01-31 08:05:36 +13:00
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.detail_preferences, rootKey)
// Dependencies (Fragments need a default constructor)
repository = Repository.getInstance(requireActivity())
serviceManager = SubscriberServiceManager(requireActivity())
notificationService = NotificationService(requireActivity())
2022-05-09 12:41:17 +12:00
resolver = requireContext().applicationContext.contentResolver
2022-01-31 08:05:36 +13:00
2022-05-07 13:03:15 +12:00
// Create result launcher for custom icon (must be created in onCreatePreferences() directly)
2022-05-09 08:04:52 +12:00
iconSetLauncher = createIconPickLauncher()
2022-05-07 13:03:15 +12:00
// Load subscription and users
val subscriptionId = arguments?.getLong(DetailActivity.EXTRA_SUBSCRIPTION_ID) ?: return
2022-05-06 13:06:21 +12:00
runBlocking {
withContext(Dispatchers.IO) {
subscription = repository.getSubscription(subscriptionId) ?: return@withContext
activity?.runOnUiThread {
loadView()
}
}
}
2022-01-31 08:05:36 +13:00
}
2022-05-06 08:56:06 +12:00
private fun loadView() {
2022-07-02 15:30:30 +12:00
if (subscription.upAppId == null) {
loadInstantPref()
loadMutedUntilPref()
loadMinPriorityPref()
loadAutoDeletePref()
loadInsistentMaxPriorityPref()
2022-07-02 15:30:30 +12:00
loadIconSetPref()
loadIconRemovePref()
if (notificationService.channelsSupported()) {
loadDedicatedChannelsPrefs()
loadOpenChannelsPrefs()
}
2022-07-02 15:30:30 +12:00
} else {
val notificationsHeaderId = context?.getString(R.string.detail_settings_notifications_header_key) ?: return
val notificationsHeader: PreferenceCategory? = findPreference(notificationsHeaderId)
notificationsHeader?.isVisible = false
}
loadDisplayNamePref()
2022-07-02 15:30:30 +12:00
loadTopicUrlPref()
2022-05-07 13:03:15 +12:00
}
private fun loadInstantPref() {
2022-05-06 13:06:21 +12:00
val appBaseUrl = getString(R.string.app_base_url)
2022-05-07 13:03:15 +12:00
val prefId = context?.getString(R.string.detail_settings_notifications_instant_key) ?: return
val pref: SwitchPreference? = findPreference(prefId)
pref?.isVisible = BuildConfig.FIREBASE_AVAILABLE && subscription.baseUrl == appBaseUrl
pref?.isChecked = subscription.instant
pref?.preferenceDataStore = object : PreferenceDataStore() {
2022-05-06 13:06:21 +12:00
override fun putBoolean(key: String?, value: Boolean) {
save(subscription.copy(instant = value), refresh = true)
}
override fun getBoolean(key: String?, defValue: Boolean): Boolean {
return subscription.instant
}
}
2022-05-07 13:03:15 +12:00
pref?.summaryProvider = Preference.SummaryProvider<SwitchPreference> { preference ->
if (preference.isChecked) {
2022-05-06 13:06:21 +12:00
getString(R.string.detail_settings_notifications_instant_summary_on)
} else {
getString(R.string.detail_settings_notifications_instant_summary_off)
}
}
2022-05-07 13:03:15 +12:00
}
2022-05-06 13:06:21 +12:00
private fun loadDedicatedChannelsPrefs() {
val prefId = context?.getString(R.string.detail_settings_notifications_dedicated_channels_key) ?: return
val pref: SwitchPreference? = findPreference(prefId)
pref?.isVisible = true
pref?.isChecked = subscription.dedicatedChannels
pref?.preferenceDataStore = object : PreferenceDataStore() {
override fun putBoolean(key: String?, value: Boolean) {
save(subscription.copy(dedicatedChannels = value))
2022-12-07 06:46:31 +13:00
if (value) {
notificationService.createSubscriptionNotificationChannels(subscription)
} else {
notificationService.deleteSubscriptionNotificationChannels(subscription)
}
openChannelsPref.isVisible = value
}
override fun getBoolean(key: String?, defValue: Boolean): Boolean {
return subscription.dedicatedChannels
}
}
pref?.summaryProvider = Preference.SummaryProvider<SwitchPreference> { preference ->
if (preference.isChecked) {
2022-12-07 16:06:59 +13:00
getString(R.string.detail_settings_notifications_dedicated_channels_summary_on)
} else {
2022-12-07 16:06:59 +13:00
getString(R.string.detail_settings_notifications_dedicated_channels_summary_off)
}
}
}
private fun loadOpenChannelsPrefs() {
val prefId = context?.getString(R.string.detail_settings_notifications_open_channels_key) ?: return
openChannelsPref = findPreference(prefId) ?: return
openChannelsPref.isVisible = subscription.dedicatedChannels
openChannelsPref.preferenceDataStore = object : PreferenceDataStore() { } // Dummy store to protect from accidentally overwriting
openChannelsPref.onPreferenceClickListener = Preference.OnPreferenceClickListener { _ ->
val settingsIntent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().applicationContext.packageName)
startActivity(settingsIntent);
true
}
}
2022-05-07 13:03:15 +12:00
private fun loadMutedUntilPref() {
val prefId = context?.getString(R.string.detail_settings_notifications_muted_until_key) ?: return
val pref: ListPreference? = findPreference(prefId)
pref?.isVisible = true // Hack: Show all settings at once, because subscription is loaded asynchronously
pref?.value = subscription.mutedUntil.toString()
pref?.preferenceDataStore = object : PreferenceDataStore() {
2022-05-06 08:56:06 +12:00
override fun putString(key: String?, value: String?) {
val mutedUntilValue = value?.toLongOrNull() ?:return
when (mutedUntilValue) {
Repository.MUTED_UNTIL_SHOW_ALL -> save(subscription.copy(mutedUntil = mutedUntilValue))
Repository.MUTED_UNTIL_FOREVER -> save(subscription.copy(mutedUntil = mutedUntilValue))
Repository.MUTED_UNTIL_TOMORROW -> {
val date = Calendar.getInstance()
date.add(Calendar.DAY_OF_MONTH, 1)
date.set(Calendar.HOUR_OF_DAY, 8)
date.set(Calendar.MINUTE, 30)
date.set(Calendar.SECOND, 0)
date.set(Calendar.MILLISECOND, 0)
save(subscription.copy(mutedUntil = date.timeInMillis/1000))
}
else -> {
val mutedUntilTimestamp = System.currentTimeMillis()/1000 + mutedUntilValue * 60
save(subscription.copy(mutedUntil = mutedUntilTimestamp))
}
}
}
override fun getString(key: String?, defValue: String?): String {
return subscription.mutedUntil.toString()
}
}
2022-12-07 14:37:30 +13:00
pref?.summaryProvider = Preference.SummaryProvider<ListPreference> {
when (val mutedUntilValue = subscription.mutedUntil) {
2022-05-06 08:56:06 +12:00
Repository.MUTED_UNTIL_SHOW_ALL -> getString(R.string.settings_notifications_muted_until_show_all)
Repository.MUTED_UNTIL_FOREVER -> getString(R.string.settings_notifications_muted_until_forever)
else -> {
val formattedDate = formatDateShort(mutedUntilValue)
getString(R.string.settings_notifications_muted_until_x, formattedDate)
}
}
}
2022-05-07 13:03:15 +12:00
}
2022-05-06 08:56:06 +12:00
2022-05-07 13:03:15 +12:00
private fun loadMinPriorityPref() {
val prefId = context?.getString(R.string.detail_settings_notifications_min_priority_key) ?: return
val pref: ListPreference? = findPreference(prefId)
pref?.isVisible = true // Hack: Show all settings at once, because subscription is loaded asynchronously
pref?.value = subscription.minPriority.toString()
pref?.preferenceDataStore = object : PreferenceDataStore() {
2022-05-06 08:56:06 +12:00
override fun putString(key: String?, value: String?) {
val minPriorityValue = value?.toIntOrNull() ?:return
save(subscription.copy(minPriority = minPriorityValue))
}
override fun getString(key: String?, defValue: String?): String {
return subscription.minPriority.toString()
}
}
2022-05-07 13:03:15 +12:00
pref?.summaryProvider = Preference.SummaryProvider<ListPreference> { preference ->
var value = preference.value.toIntOrNull() ?: Repository.MIN_PRIORITY_USE_GLOBAL
2022-05-06 08:56:06 +12:00
val global = value == Repository.MIN_PRIORITY_USE_GLOBAL
if (value == Repository.MIN_PRIORITY_USE_GLOBAL) {
value = repository.getMinPriority()
}
val summary = when (value) {
PRIORITY_MIN -> getString(R.string.settings_notifications_min_priority_summary_any)
PRIORITY_MAX -> getString(R.string.settings_notifications_min_priority_summary_max)
2022-05-06 08:56:06 +12:00
else -> {
val minPriorityString = toPriorityString(requireContext(), value)
getString(R.string.settings_notifications_min_priority_summary_x_or_higher, value, minPriorityString)
}
}
maybeAppendGlobal(summary, global)
}
2022-05-07 13:03:15 +12:00
}
2022-05-06 08:56:06 +12:00
2022-05-07 13:03:15 +12:00
private fun loadAutoDeletePref() {
val prefId = context?.getString(R.string.detail_settings_notifications_auto_delete_key) ?: return
val pref: ListPreference? = findPreference(prefId)
pref?.isVisible = true // Hack: Show all settings at once, because subscription is loaded asynchronously
pref?.value = subscription.autoDelete.toString()
pref?.preferenceDataStore = object : PreferenceDataStore() {
2022-05-06 08:56:06 +12:00
override fun putString(key: String?, value: String?) {
val seconds = value?.toLongOrNull() ?:return
save(subscription.copy(autoDelete = seconds))
}
override fun getString(key: String?, defValue: String?): String {
return subscription.autoDelete.toString()
}
}
2022-05-07 13:03:15 +12:00
pref?.summaryProvider = Preference.SummaryProvider<ListPreference> { preference ->
var seconds = preference.value.toLongOrNull() ?: Repository.AUTO_DELETE_USE_GLOBAL
2022-05-06 08:56:06 +12:00
val global = seconds == Repository.AUTO_DELETE_USE_GLOBAL
if (global) {
2022-05-06 08:56:06 +12:00
seconds = repository.getAutoDeleteSeconds()
}
val summary = when (seconds) {
Repository.AUTO_DELETE_NEVER -> getString(R.string.settings_notifications_auto_delete_summary_never)
Repository.AUTO_DELETE_ONE_DAY_SECONDS -> getString(R.string.settings_notifications_auto_delete_summary_one_day)
Repository.AUTO_DELETE_THREE_DAYS_SECONDS -> getString(R.string.settings_notifications_auto_delete_summary_three_days)
Repository.AUTO_DELETE_ONE_WEEK_SECONDS -> getString(R.string.settings_notifications_auto_delete_summary_one_week)
Repository.AUTO_DELETE_ONE_MONTH_SECONDS -> getString(R.string.settings_notifications_auto_delete_summary_one_month)
Repository.AUTO_DELETE_THREE_MONTHS_SECONDS -> getString(R.string.settings_notifications_auto_delete_summary_three_months)
else -> getString(R.string.settings_notifications_auto_delete_summary_one_month) // Must match default const
}
maybeAppendGlobal(summary, global)
}
}
private fun loadInsistentMaxPriorityPref() {
val prefId = context?.getString(R.string.detail_settings_notifications_insistent_max_priority_key) ?: return
val pref: ListPreference? = findPreference(prefId)
2022-12-05 14:11:46 +13:00
pref?.isVisible = true
pref?.value = subscription.insistent.toString()
2022-12-05 14:11:46 +13:00
pref?.preferenceDataStore = object : PreferenceDataStore() {
override fun putString(key: String?, value: String?) {
val intValue = value?.toIntOrNull() ?:return
save(subscription.copy(insistent = intValue))
2022-12-05 14:11:46 +13:00
}
override fun getString(key: String?, defValue: String?): String {
return subscription.insistent.toString()
2022-12-05 14:11:46 +13:00
}
}
pref?.summaryProvider = Preference.SummaryProvider<ListPreference> { preference ->
val value = preference.value.toIntOrNull() ?: Repository.INSISTENT_MAX_PRIORITY_USE_GLOBAL
val global = value == Repository.INSISTENT_MAX_PRIORITY_USE_GLOBAL
val enabled = if (global) repository.getInsistentMaxPriorityEnabled() else value == Repository.INSISTENT_MAX_PRIORITY_ENABLED
val summary = if (enabled) {
getString(R.string.settings_notifications_insistent_max_priority_summary_enabled)
2022-12-05 14:11:46 +13:00
} else {
getString(R.string.settings_notifications_insistent_max_priority_summary_disabled)
2022-12-05 14:11:46 +13:00
}
maybeAppendGlobal(summary, global)
2022-05-06 08:56:06 +12:00
}
}
2022-05-09 08:04:52 +12:00
private fun loadIconSetPref() {
val prefId = context?.getString(R.string.detail_settings_appearance_icon_set_key) ?: return
iconSetPref = findPreference(prefId) ?: return
iconSetPref.isVisible = subscription.icon == null
iconSetPref.preferenceDataStore = object : PreferenceDataStore() { } // Dummy store to protect from accidentally overwriting
2022-12-07 14:37:30 +13:00
iconSetPref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
2022-05-09 08:04:52 +12:00
iconSetLauncher.launch("image/*")
true
}
}
private fun loadIconRemovePref() {
val prefId = context?.getString(R.string.detail_settings_appearance_icon_remove_key) ?: return
iconRemovePref = findPreference(prefId) ?: return
2022-05-09 12:41:17 +12:00
iconRemovePref.isVisible = subscription.icon != null
iconRemovePref.preferenceDataStore = object : PreferenceDataStore() { } // Dummy store to protect from accidentally overwriting
2022-12-07 14:37:30 +13:00
iconRemovePref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
2022-05-09 12:41:17 +12:00
iconRemovePref.isVisible = false
iconSetPref.isVisible = true
deleteIcon(subscription.icon)
save(subscription.copy(icon = null))
true
}
2022-05-09 08:04:52 +12:00
2022-05-09 12:41:17 +12:00
// Set icon (if it exists)
2022-05-09 08:04:52 +12:00
if (subscription.icon != null) {
try {
2022-05-09 14:57:52 +12:00
val bitmap = subscription.icon!!.readBitmapFromUri(requireContext())
2022-05-09 08:04:52 +12:00
iconRemovePref.icon = bitmap.toDrawable(resources)
} catch (e: Exception) {
2022-05-09 12:41:17 +12:00
Log.w(TAG, "Unable to set icon ${subscription.icon}", e)
2022-05-09 08:04:52 +12:00
}
}
2022-05-07 13:03:15 +12:00
}
private fun loadDisplayNamePref() {
val prefId = context?.getString(R.string.detail_settings_appearance_display_name_key) ?: return
val pref: EditTextPreference? = findPreference(prefId)
pref?.isVisible = true // Hack: Show all settings at once, because subscription is loaded asynchronously
pref?.text = subscription.displayName
2022-06-25 04:55:41 +12:00
pref?.dialogMessage = getString(R.string.detail_settings_appearance_display_name_message, topicShortUrl(subscription.baseUrl, subscription.topic))
pref?.preferenceDataStore = object : PreferenceDataStore() {
override fun putString(key: String?, value: String?) {
2022-12-07 16:06:59 +13:00
val displayName = if (value != "") value else null
val newSubscription = subscription.copy(displayName = displayName)
2022-06-25 04:19:53 +12:00
save(newSubscription)
2022-12-07 16:06:59 +13:00
// Update activity title
activity?.runOnUiThread {
activity?.title = displayName(newSubscription)
}
2022-12-07 16:06:59 +13:00
// Update dedicated notification channel
if (newSubscription.dedicatedChannels) {
notificationService.createSubscriptionNotificationChannels(newSubscription)
}
}
override fun getString(key: String?, defValue: String?): String {
return subscription.displayName ?: ""
}
}
pref?.summaryProvider = Preference.SummaryProvider<EditTextPreference> { provider ->
if (TextUtils.isEmpty(provider.text)) {
getString(
R.string.detail_settings_appearance_display_name_default_summary,
displayName(subscription)
)
} else {
provider.text
}
}
}
2022-07-02 15:30:30 +12:00
private fun loadTopicUrlPref() {
// Topic URL
val topicUrlPrefId = context?.getString(R.string.detail_settings_about_topic_url_key) ?: return
val topicUrlPref: Preference? = findPreference(topicUrlPrefId)
val topicUrl = topicShortUrl(subscription.baseUrl, subscription.topic)
topicUrlPref?.summary = topicUrl
topicUrlPref?.onPreferenceClickListener = OnPreferenceClickListener {
val context = context ?: return@OnPreferenceClickListener false
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText("topic url", topicUrl)
clipboard.setPrimaryClip(clip)
Toast
.makeText(context, getString(R.string.detail_settings_about_topic_url_copied_to_clipboard_message), Toast.LENGTH_LONG)
.show()
true
}
}
2022-05-09 08:04:52 +12:00
private fun createIconPickLauncher(): ActivityResultLauncher<String> {
2022-05-07 13:03:15 +12:00
return registerForActivityResult(ActivityResultContracts.GetContent()) { inputUri ->
if (inputUri == null) {
return@registerForActivityResult
}
lifecycleScope.launch(Dispatchers.IO) {
2022-05-09 12:41:17 +12:00
val outputUri = createUri() ?: return@launch
2022-05-07 13:03:15 +12:00
try {
2022-05-10 02:23:21 +12:00
// Early size & mime type check
val mimeType = resolver.getType(inputUri)
if (!supportedImage(mimeType)) {
throw IOException("unknown image type or not supported")
}
val stat = fileStat(requireContext(), inputUri) // May throw
if (stat.size > SUBSCRIPTION_ICON_MAX_SIZE_BYTES) {
throw IOException("image too large, max supported is ${SUBSCRIPTION_ICON_MAX_SIZE_BYTES/1024/1024}MB")
}
2022-05-09 08:04:52 +12:00
// Write to cache storage
2022-05-07 13:03:15 +12:00
val inputStream = resolver.openInputStream(inputUri) ?: throw IOException("Couldn't open content URI for reading")
val outputStream = resolver.openOutputStream(outputUri) ?: throw IOException("Couldn't open content URI for writing")
2022-05-09 12:41:17 +12:00
inputStream.use {
it.copyTo(outputStream)
}
2022-05-09 08:04:52 +12:00
2022-05-10 02:23:21 +12:00
// Read image, check dimensions
2022-05-09 14:57:52 +12:00
val bitmap = outputUri.readBitmapFromUri(requireContext())
2022-05-10 02:23:21 +12:00
if (bitmap.width > SUBSCRIPTION_ICON_MAX_WIDTH || bitmap.height > SUBSCRIPTION_ICON_MAX_HEIGHT) {
throw IOException("image exceeds max dimensions of ${SUBSCRIPTION_ICON_MAX_WIDTH}x${SUBSCRIPTION_ICON_MAX_HEIGHT}")
}
// Display "remove" preference
2022-05-09 08:04:52 +12:00
iconRemovePref.icon = bitmap.toDrawable(resources)
iconRemovePref.isVisible = true
2022-05-09 12:41:17 +12:00
iconSetPref.isVisible = false
// Finally, save (this is last!)
save(subscription.copy(icon = outputUri.toString()))
2022-05-07 13:03:15 +12:00
} catch (e: Exception) {
Log.w(TAG, "Saving icon failed", e)
requireActivity().runOnUiThread {
2022-05-09 12:41:17 +12:00
Toast.makeText(context, getString(R.string.detail_settings_appearance_icon_error_saving, e.message), Toast.LENGTH_LONG).show()
2022-05-07 13:03:15 +12:00
}
}
}
}
}
2022-05-09 12:41:17 +12:00
private fun createUri(): Uri? {
2022-05-07 13:03:15 +12:00
val dir = File(requireContext().cacheDir, SUBSCRIPTION_ICONS)
if (!dir.exists() && !dir.mkdirs()) {
2022-05-09 12:41:17 +12:00
return null
2022-05-07 13:03:15 +12:00
}
val file = File(dir, subscription.id.toString())
2022-07-17 08:32:09 +12:00
return FileProvider.getUriForFile(requireContext(), DownloadAttachmentWorker.FILE_PROVIDER_AUTHORITY, file)
2022-05-07 13:03:15 +12:00
}
2022-05-09 12:41:17 +12:00
private fun deleteIcon(uri: String?) {
if (uri == null) {
return
}
try {
resolver.delete(Uri.parse(uri), null, null)
} catch (e: Exception) {
Log.w(TAG, "Unable to delete $uri", e)
}
2022-05-09 08:04:52 +12:00
}
2022-05-06 13:06:21 +12:00
private fun save(newSubscription: Subscription, refresh: Boolean = false) {
2022-05-06 08:56:06 +12:00
subscription = newSubscription
lifecycleScope.launch(Dispatchers.IO) {
repository.updateSubscription(newSubscription)
2022-05-06 13:06:21 +12:00
if (refresh) {
SubscriberServiceManager.refresh(requireContext())
}
2022-05-06 08:56:06 +12:00
}
}
private fun maybeAppendGlobal(summary: String, global: Boolean): String {
return if (global) {
2022-05-06 13:06:21 +12:00
summary + " (" + getString(R.string.detail_settings_global_setting_suffix) + ")"
2022-05-06 08:56:06 +12:00
} else {
summary
}
}
2022-01-31 08:05:36 +13:00
}
companion object {
private const val TAG = "NtfyDetailSettingsActiv"
2022-05-07 13:03:15 +12:00
private const val SUBSCRIPTION_ICONS = "subscriptionIcons"
2022-05-10 02:23:21 +12:00
private const val SUBSCRIPTION_ICON_MAX_SIZE_BYTES = 4194304
private const val SUBSCRIPTION_ICON_MAX_WIDTH = 2048
private const val SUBSCRIPTION_ICON_MAX_HEIGHT = 2048
2022-01-31 08:05:36 +13:00
}
}