new notification warner

Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
This commit is contained in:
Marcel Hibbe 2024-11-29 18:04:31 +01:00
parent 2340272d43
commit 22517c8ec9
No known key found for this signature in database
GPG Key ID: C793F8B59F43CE7B
7 changed files with 148 additions and 46 deletions

View File

@ -275,7 +275,7 @@ class ConversationsListActivity :
adapter!!.addListener(this) adapter!!.addListener(this)
prepareViews() prepareViews()
updateNotificationWarning() showNotificationWarning()
showShareToScreen = hasActivityActionSendIntent() showShareToScreen = hasActivityActionSendIntent()
@ -296,6 +296,11 @@ class ConversationsListActivity :
loadUserAvatar(binding.switchAccountButton) loadUserAvatar(binding.switchAccountButton)
viewThemeUtils.material.colorMaterialTextButton(binding.switchAccountButton) viewThemeUtils.material.colorMaterialTextButton(binding.switchAccountButton)
viewThemeUtils.material.themeCardView(binding.conversationListHintInclude.hintLayoutCardview) viewThemeUtils.material.themeCardView(binding.conversationListHintInclude.hintLayoutCardview)
viewThemeUtils.material.themeCardView(binding.conversationListNotificationWarning.hintLayoutCardview)
viewThemeUtils.material.colorMaterialButtonText(binding.conversationListNotificationWarning.notNowButton)
viewThemeUtils.material.colorMaterialButtonText(
binding.conversationListNotificationWarning.showSettingsButton
)
searchBehaviorSubject.onNext(false) searchBehaviorSubject.onNext(false)
fetchRooms() fetchRooms()
fetchPendingInvitations() fetchPendingInvitations()
@ -307,14 +312,6 @@ class ConversationsListActivity :
showSearchOrToolbar() showSearchOrToolbar()
} }
private fun updateNotificationWarning() {
if (shouldShowNotificationWarning()) {
showNotificationWarning()
} else {
binding.chatListNotificationWarning.visibility = View.GONE
}
}
private fun initObservers() { private fun initObservers() {
this.lifecycleScope.launch { this.lifecycleScope.launch {
networkMonitor.isOnline.onEach { isOnline -> networkMonitor.isOnline.onEach { isOnline ->
@ -1502,17 +1499,46 @@ class ConversationsListActivity :
} }
private fun showNotificationWarning() { private fun showNotificationWarning() {
binding.chatListNotificationWarning.visibility = View.VISIBLE if (shouldShowNotificationWarning()) {
binding.chatListNotificationWarning.setOnClickListener { binding.conversationListNotificationWarning.conversationListHintLayout.visibility = View.VISIBLE
val bundle = Bundle() binding.conversationListNotificationWarning.notNowButton.setOnClickListener {
bundle.putBoolean(KEY_SCROLL_TO_NOTIFICATION_CATEGORY, true) binding.conversationListNotificationWarning.conversationListHintLayout.visibility = View.GONE
val settingsIntent = Intent(context, SettingsActivity::class.java) val lastWarningDate = System.currentTimeMillis()
settingsIntent.putExtras(bundle) appPreferences.setNotificationWarningLastPostponedDate(lastWarningDate)
startActivity(settingsIntent) }
binding.conversationListNotificationWarning.showSettingsButton.setOnClickListener {
val bundle = Bundle()
bundle.putBoolean(KEY_SCROLL_TO_NOTIFICATION_CATEGORY, true)
val settingsIntent = Intent(context, SettingsActivity::class.java)
settingsIntent.putExtras(bundle)
startActivity(settingsIntent)
}
} else {
binding.conversationListNotificationWarning.conversationListHintLayout.visibility = View.GONE
} }
} }
private fun shouldShowNotificationWarning(): Boolean { private fun shouldShowNotificationWarning(): Boolean {
fun shouldShowWarningIfDateTooOld(date1: Long): Boolean {
val currentTimeMillis = System.currentTimeMillis()
val differenceMillis = currentTimeMillis - date1
val daysForWarningInMillis = TimeUnit.DAYS.toMillis(DAYS_FOR_NOTIFICATION_WARNING)
return differenceMillis > daysForWarningInMillis
}
fun shouldShowNotificationWarningByUserChoice(): Boolean {
if (appPreferences.showRegularNotificationWarning) {
val lastWarningDate = appPreferences.getNotificationWarningLastPostponedDate()
return if (lastWarningDate == NOTIFICATION_WARNING_DATE_NOT_SET) {
true
} else {
shouldShowWarningIfDateTooOld(lastWarningDate)
}
} else {
return false
}
}
val notificationPermissionNotGranted = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && val notificationPermissionNotGranted = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
!platformPermissionUtil.isPostNotificationsPermissionGranted() !platformPermissionUtil.isPostNotificationsPermissionGranted()
val batteryOptimizationNotIgnored = !PowerManagerUtils().isIgnoringBatteryOptimizations() val batteryOptimizationNotIgnored = !PowerManagerUtils().isIgnoringBatteryOptimizations()
@ -1529,10 +1555,8 @@ class ConversationsListActivity :
callsChannelNotEnabled || callsChannelNotEnabled ||
!serverNotificationAppInstalled !serverNotificationAppInstalled
val userWantsToBeNotifiedAboutWrongSettings = appPreferences.getShowNotificationWarning()
return settingsOfUserAreWrong && return settingsOfUserAreWrong &&
userWantsToBeNotifiedAboutWrongSettings && shouldShowNotificationWarningByUserChoice() &&
ClosedInterfaceImpl().isGooglePlayServicesAvailable ClosedInterfaceImpl().isGooglePlayServicesAvailable
} }
@ -1927,5 +1951,7 @@ class ConversationsListActivity :
const val MAINTENANCE_MODE_HEADER_KEY = "X-Nextcloud-Maintenance-Mode" const val MAINTENANCE_MODE_HEADER_KEY = "X-Nextcloud-Maintenance-Mode"
const val REQUEST_POST_NOTIFICATIONS_PERMISSION = 111 const val REQUEST_POST_NOTIFICATIONS_PERMISSION = 111
const val BADGE_OFFSET = 35 const val BADGE_OFFSET = 35
const val DAYS_FOR_NOTIFICATION_WARNING = 5L
const val NOTIFICATION_WARNING_DATE_NOT_SET = 0L
} }
} }

View File

@ -54,6 +54,7 @@ import com.nextcloud.talk.api.NcApiCoroutines
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.setAppTheme import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.setAppTheme
import com.nextcloud.talk.conversationlist.ConversationsListActivity import com.nextcloud.talk.conversationlist.ConversationsListActivity
import com.nextcloud.talk.conversationlist.ConversationsListActivity.Companion.NOTIFICATION_WARNING_DATE_NOT_SET
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.ActivitySettingsBinding import com.nextcloud.talk.databinding.ActivitySettingsBinding
import com.nextcloud.talk.diagnose.DiagnoseActivity import com.nextcloud.talk.diagnose.DiagnoseActivity
@ -927,13 +928,16 @@ class SettingsActivity :
private fun setupCheckables() { private fun setupCheckables() {
binding.settingsShowNotificationWarningSwitch.isChecked = binding.settingsShowNotificationWarningSwitch.isChecked =
appPreferences.showNotificationWarning appPreferences.showRegularNotificationWarning
if (ClosedInterfaceImpl().isGooglePlayServicesAvailable) { if (ClosedInterfaceImpl().isGooglePlayServicesAvailable) {
binding.settingsShowNotificationWarning.setOnClickListener { binding.settingsShowNotificationWarning.setOnClickListener {
val isChecked = binding.settingsShowNotificationWarningSwitch.isChecked val isChecked = binding.settingsShowNotificationWarningSwitch.isChecked
binding.settingsShowNotificationWarningSwitch.isChecked = !isChecked binding.settingsShowNotificationWarningSwitch.isChecked = !isChecked
appPreferences.setShowNotificationWarning(!isChecked) appPreferences.setShowRegularNotificationWarning(!isChecked)
if (!isChecked) {
appPreferences.setNotificationWarningLastPostponedDate(NOTIFICATION_WARNING_DATE_NOT_SET)
}
} }
} else { } else {
binding.settingsShowNotificationWarning.visibility = View.GONE binding.settingsShowNotificationWarning.visibility = View.GONE
@ -1427,5 +1431,6 @@ class SettingsActivity :
private const val LINEBREAK = "\n" private const val LINEBREAK = "\n"
const val HTTP_CODE_OK: Int = 200 const val HTTP_CODE_OK: Int = 200
const val HTTP_ERROR_CODE_BAD_REQUEST: Int = 400 const val HTTP_ERROR_CODE_BAD_REQUEST: Int = 400
const val NO_NOTIFICATION_REMINDER_WANTED = 0L
} }
} }

View File

@ -178,9 +178,13 @@ public interface AppPreferences {
void deleteAllMessageQueuesFor(String userId); void deleteAllMessageQueuesFor(String userId);
boolean getShowNotificationWarning(); Long getNotificationWarningLastPostponedDate();
void setShowNotificationWarning(boolean showNotificationWarning); void setNotificationWarningLastPostponedDate(Long showNotificationWarning);
Boolean getShowRegularNotificationWarning();
void setShowRegularNotificationWarning(boolean value);
void clear(); void clear();
} }

View File

@ -392,6 +392,17 @@ class AppPreferencesImpl(val context: Context) : AppPreferences {
} }
} }
override fun getShowRegularNotificationWarning (): Boolean {
return runBlocking { async { readBoolean(SHOW_REGULAR_NOTIFICATION_WARNING, true).first() } }.getCompleted()
}
override fun setShowRegularNotificationWarning(value: Boolean) =
runBlocking<Unit> {
async {
writeBoolean(SHOW_REGULAR_NOTIFICATION_WARNING, value)
}
}
override fun setPhoneBookIntegrationLastRun(currentTimeMillis: Long) = override fun setPhoneBookIntegrationLastRun(currentTimeMillis: Long) =
runBlocking<Unit> { runBlocking<Unit> {
async { async {
@ -544,18 +555,14 @@ class AppPreferencesImpl(val context: Context) : AppPreferences {
} }
} }
override fun getShowNotificationWarning(): Boolean { override fun getNotificationWarningLastPostponedDate(): Long {
return runBlocking { return runBlocking { async { readLong(LAST_NOTIFICATION_WARNING).first() } }.getCompleted()
async {
readBoolean(SHOW_NOTIFICATION_WARNING, true).first()
}
}.getCompleted()
} }
override fun setShowNotificationWarning(showNotificationWarning: Boolean) = override fun setNotificationWarningLastPostponedDate(showNotificationWarning: Long) =
runBlocking<Unit> { runBlocking<Unit> {
async { async {
writeBoolean(SHOW_NOTIFICATION_WARNING, showNotificationWarning) writeLong(LAST_NOTIFICATION_WARNING, showNotificationWarning)
} }
} }
@ -643,7 +650,8 @@ class AppPreferencesImpl(val context: Context) : AppPreferences {
const val PHONE_BOOK_INTEGRATION_LAST_RUN = "phone_book_integration_last_run" const val PHONE_BOOK_INTEGRATION_LAST_RUN = "phone_book_integration_last_run"
const val TYPING_STATUS = "typing_status" const val TYPING_STATUS = "typing_status"
const val MESSAGE_QUEUE = "@message_queue" const val MESSAGE_QUEUE = "@message_queue"
const val SHOW_NOTIFICATION_WARNING = "show_notification_warning" const val SHOW_REGULAR_NOTIFICATION_WARNING = "show_regular_notification_warning"
const val LAST_NOTIFICATION_WARNING = "last_notification_warning"
private fun String.convertStringToArray(): Array<Float> { private fun String.convertStringToArray(): Array<Float> {
var varString = this var varString = this
val floatList = mutableListOf<Float>() val floatList = mutableListOf<Float>()

View File

@ -37,18 +37,6 @@
android:visibility="gone" android:visibility="gone"
tools:visibility="visible" /> tools:visibility="visible" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/chat_list_notification_warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/nc_warning"
android:gravity="center"
android:minHeight="40dp"
android:text="@string/nc_notification_warning"
android:textColor="@color/white"
android:visibility="gone"
tools:visibility="visible" />
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:id="@+id/search_toolbar" android:id="@+id/search_toolbar"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -238,6 +226,10 @@
android:id="@+id/conversation_list_hint_include" android:id="@+id/conversation_list_hint_include"
layout="@layout/federated_invitation_hint" /> layout="@layout/federated_invitation_hint" />
<include
android:id="@+id/conversation_list_notification_warning"
layout="@layout/notifications_warning" />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view" android:id="@+id/recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2024 Marcel Hibbe <dev@mhibbe.de>
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<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:id="@+id/conversation_list_hint_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center_vertical|center_horizontal"
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
android:id="@+id/hint_layout_cardview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/standard_margin"
android:layout_marginTop="@dimen/standard_half_margin"
android:layout_marginEnd="@dimen/standard_margin"
app:cardCornerRadius="8dp"
app:cardElevation="2dp"
app:strokeWidth="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/margin_between_elements">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/nc_notification_warning"
android:textAlignment="center" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/not_now_button"
style="@style/Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/nc_not_now"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/show_settings_button"
style="@style/Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/nc_settings"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>

View File

@ -182,9 +182,10 @@ How to translate with transifex:
<string name="nc_ignore_battery_optimization_dialog_title">Ignore battery optimization</string> <string name="nc_ignore_battery_optimization_dialog_title">Ignore battery optimization</string>
<string name="nc_ignore_battery_optimization_dialog_text">Battery optimization is not ignored. This should be changed to make sure that notifications work in the background! Please click OK and select \"All apps\" -> %1$s -> Do not optimize</string> <string name="nc_ignore_battery_optimization_dialog_text">Battery optimization is not ignored. This should be changed to make sure that notifications work in the background! Please click OK and select \"All apps\" -> %1$s -> Do not optimize</string>
<string name="nc_show_notification_warning_title">Show notification warning</string> <string name="nc_show_notification_warning_title">Show regular notification warning</string>
<string name="nc_show_notification_warning_description">When notifications are not set up correctly, show a warning</string> <string name="nc_show_notification_warning_description">When notifications are not set up correctly, show a regular warning</string>
<string name="nc_notification_warning">Notifications are not set up correctly</string> <string name="nc_notification_warning">Notifications are not set up correctly</string>
<string name="nc_not_now">Not now</string>
<string name="nc_diagnose_meta_category_title">Meta information</string> <string name="nc_diagnose_meta_category_title">Meta information</string>
<string name="nc_diagnose_meta_system_report_date">Generation of system report</string> <string name="nc_diagnose_meta_system_report_date">Generation of system report</string>