forked from github/wulkanowy-mirror
Add notification piggyback (#1503)
This commit is contained in:
@ -14,7 +14,6 @@ import io.github.wulkanowy.sdk.toLocalDate
|
||||
import io.github.wulkanowy.ui.modules.dashboard.DashboardItem
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeAverageMode
|
||||
import io.github.wulkanowy.ui.modules.grade.GradeSortingMode
|
||||
import io.github.wulkanowy.utils.toTimestamp
|
||||
import io.github.wulkanowy.utils.toLocalDateTime
|
||||
import io.github.wulkanowy.utils.toTimestamp
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
@ -108,6 +107,14 @@ class PreferencesRepository @Inject constructor(
|
||||
R.bool.pref_default_notification_upcoming_lessons_enable
|
||||
)
|
||||
|
||||
val isNotificationPiggybackEnabledKey =
|
||||
context.getString(R.string.pref_key_notifications_piggyback)
|
||||
val isNotificationPiggybackEnabled: Boolean
|
||||
get() = getBoolean(
|
||||
R.string.pref_key_notifications_piggyback,
|
||||
R.bool.pref_default_notification_piggyback
|
||||
)
|
||||
|
||||
val isDebugNotificationEnableKey = context.getString(R.string.pref_key_notification_debug)
|
||||
val isDebugNotificationEnable: Boolean
|
||||
get() = getBoolean(isDebugNotificationEnableKey, R.bool.pref_default_notification_debug)
|
||||
@ -176,10 +183,8 @@ class PreferencesRepository @Inject constructor(
|
||||
)
|
||||
|
||||
var lasSyncDate: LocalDateTime
|
||||
get() = getLong(
|
||||
R.string.pref_key_last_sync_date,
|
||||
R.string.pref_default_last_sync_date
|
||||
).toLocalDateTime()
|
||||
get() = getLong(R.string.pref_key_last_sync_date, R.string.pref_default_last_sync_date)
|
||||
.toLocalDateTime()
|
||||
set(value) = sharedPref.edit().putLong("last_sync_date", value.toTimestamp()).apply()
|
||||
|
||||
var dashboardItemsPosition: Map<DashboardItem.Type, Int>?
|
||||
@ -230,8 +235,10 @@ class PreferencesRepository @Inject constructor(
|
||||
set(value) = sharedPref.edit().putInt(PREF_KEY_IN_APP_REVIEW_COUNT, value).apply()
|
||||
|
||||
var inAppReviewDate: LocalDate?
|
||||
get() = sharedPref.getLong(PREF_KEY_IN_APP_REVIEW_DATE, 0).takeIf { it != 0L }?.toLocalDate()
|
||||
set(value) = sharedPref.edit().putLong(PREF_KEY_IN_APP_REVIEW_DATE, value!!.toTimestamp()).apply()
|
||||
get() = sharedPref.getLong(PREF_KEY_IN_APP_REVIEW_DATE, 0).takeIf { it != 0L }
|
||||
?.toLocalDate()
|
||||
set(value) = sharedPref.edit().putLong(PREF_KEY_IN_APP_REVIEW_DATE, value!!.toTimestamp())
|
||||
.apply()
|
||||
|
||||
var isAppReviewDone: Boolean
|
||||
get() = sharedPref.getBoolean(PREF_KEY_IN_APP_REVIEW_DONE, false)
|
||||
|
@ -0,0 +1,24 @@
|
||||
package io.github.wulkanowy.services.piggyback
|
||||
|
||||
import android.service.notification.NotificationListenerService
|
||||
import android.service.notification.StatusBarNotification
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import io.github.wulkanowy.data.repositories.PreferencesRepository
|
||||
import io.github.wulkanowy.services.sync.SyncManager
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
class VulcanNotificationListenerService : NotificationListenerService() {
|
||||
|
||||
@Inject
|
||||
lateinit var syncManager: SyncManager
|
||||
|
||||
@Inject
|
||||
lateinit var preferenceRepository: PreferencesRepository
|
||||
|
||||
override fun onNotificationPosted(statusBarNotification: StatusBarNotification?) {
|
||||
if (statusBarNotification?.packageName == "pl.edu.vulcan.hebe" && preferenceRepository.isNotificationPiggybackEnabled) {
|
||||
syncManager.startOneTimeSyncWorker()
|
||||
}
|
||||
}
|
||||
}
|
@ -57,14 +57,20 @@ class SyncManager @Inject constructor(
|
||||
|
||||
fun startPeriodicSyncWorker(restart: Boolean = false) {
|
||||
if (preferencesRepository.isServiceEnabled && !now().isHolidays) {
|
||||
workManager.enqueueUniquePeriodicWork(SyncWorker::class.java.simpleName, if (restart) REPLACE else KEEP,
|
||||
PeriodicWorkRequestBuilder<SyncWorker>(preferencesRepository.servicesInterval, MINUTES)
|
||||
val serviceInterval = preferencesRepository.servicesInterval
|
||||
|
||||
workManager.enqueueUniquePeriodicWork(
|
||||
SyncWorker::class.java.simpleName, if (restart) REPLACE else KEEP,
|
||||
PeriodicWorkRequestBuilder<SyncWorker>(serviceInterval, MINUTES)
|
||||
.setInitialDelay(10, MINUTES)
|
||||
.setBackoffCriteria(EXPONENTIAL, 30, MINUTES)
|
||||
.setConstraints(Constraints.Builder()
|
||||
.setRequiredNetworkType(if (preferencesRepository.isServicesOnlyWifi) UNMETERED else CONNECTED)
|
||||
.build())
|
||||
.build())
|
||||
.setConstraints(
|
||||
Constraints.Builder()
|
||||
.setRequiredNetworkType(if (preferencesRepository.isServicesOnlyWifi) UNMETERED else CONNECTED)
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,7 +83,11 @@ class SyncManager @Inject constructor(
|
||||
)
|
||||
.build()
|
||||
|
||||
workManager.enqueueUniqueWork("${SyncWorker::class.java.simpleName}_one_time", ExistingWorkPolicy.REPLACE, work)
|
||||
workManager.enqueueUniqueWork(
|
||||
"${SyncWorker::class.java.simpleName}_one_time",
|
||||
ExistingWorkPolicy.REPLACE,
|
||||
work
|
||||
)
|
||||
|
||||
return workManager.getWorkInfoByIdLiveData(work.id).asFlow()
|
||||
}
|
||||
|
@ -10,9 +10,12 @@ import android.provider.Settings
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import androidx.preference.SwitchPreferenceCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.thelittlefireman.appkillermanager.AppKillerManager
|
||||
import com.thelittlefireman.appkillermanager.exceptions.NoActionFoundException
|
||||
@ -43,6 +46,21 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
||||
|
||||
override val titleStringId get() = R.string.pref_settings_notifications_title
|
||||
|
||||
override val isNotificationPermissionGranted: Boolean
|
||||
get() {
|
||||
val packageNameList =
|
||||
NotificationManagerCompat.getEnabledListenerPackages(requireContext())
|
||||
val appPackageName = requireContext().packageName
|
||||
|
||||
return appPackageName in packageNameList
|
||||
}
|
||||
|
||||
private val notificationSettingsContract =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
|
||||
presenter.onNotificationPermissionResult()
|
||||
}
|
||||
|
||||
override fun initView(showDebugNotificationSwitch: Boolean) {
|
||||
findPreference<Preference>(getString(R.string.pref_key_notification_debug))?.isVisible =
|
||||
showDebugNotificationSwitch
|
||||
@ -57,12 +75,11 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
||||
}
|
||||
}
|
||||
|
||||
findPreference<Preference>(getString(R.string.pref_key_notifications_system_settings))?.run {
|
||||
setOnPreferenceClickListener {
|
||||
findPreference<Preference>(getString(R.string.pref_key_notifications_system_settings))
|
||||
?.setOnPreferenceClickListener {
|
||||
presenter.onOpenSystemSettingsClicked()
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateRecyclerView(
|
||||
@ -157,6 +174,24 @@ class NotificationsFragment : PreferenceFragmentCompat(),
|
||||
}
|
||||
}
|
||||
|
||||
override fun openNotificationPermissionDialog() {
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setTitle(getString(R.string.pref_notification_piggyback_popup_title))
|
||||
.setMessage(getString(R.string.pref_notification_piggyback_popup_description))
|
||||
.setPositiveButton(getString(R.string.pref_notification_piggyback_popup_positive)) { _, _ ->
|
||||
notificationSettingsContract.launch(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"))
|
||||
}
|
||||
.setNegativeButton(android.R.string.cancel) { _, _ ->
|
||||
setNotificationPiggybackPreferenceChecked(false)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean) {
|
||||
findPreference<SwitchPreferenceCompat>(getString(R.string.pref_key_notifications_piggyback))?.isChecked =
|
||||
isChecked
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
preferenceScreen.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
|
||||
|
@ -31,6 +31,9 @@ class NotificationsPresenter @Inject constructor(
|
||||
)
|
||||
initView(appInfo.isDebug)
|
||||
}
|
||||
|
||||
checkNotificationPiggybackState()
|
||||
|
||||
Timber.i("Settings notifications view was initialized")
|
||||
}
|
||||
|
||||
@ -47,6 +50,11 @@ class NotificationsPresenter @Inject constructor(
|
||||
isDebugNotificationEnableKey -> {
|
||||
chuckerCollector.showNotification = isDebugNotificationEnable
|
||||
}
|
||||
isNotificationPiggybackEnabledKey -> {
|
||||
if (isNotificationPiggybackEnabled && view?.isNotificationPermissionGranted == false) {
|
||||
view?.openNotificationPermissionDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
analytics.logEvent("setting_changed", "name" to key)
|
||||
@ -59,4 +67,18 @@ class NotificationsPresenter @Inject constructor(
|
||||
fun onOpenSystemSettingsClicked() {
|
||||
view?.openSystemSettings()
|
||||
}
|
||||
|
||||
fun onNotificationPermissionResult() {
|
||||
view?.run {
|
||||
setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkNotificationPiggybackState() {
|
||||
if (preferencesRepository.isNotificationPiggybackEnabled) {
|
||||
view?.run {
|
||||
setNotificationPiggybackPreferenceChecked(isNotificationPermissionGranted)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import io.github.wulkanowy.ui.base.BaseView
|
||||
|
||||
interface NotificationsView : BaseView {
|
||||
|
||||
val isNotificationPermissionGranted: Boolean
|
||||
|
||||
fun initView(showDebugNotificationSwitch: Boolean)
|
||||
|
||||
fun showFixSyncDialog()
|
||||
@ -11,4 +13,8 @@ interface NotificationsView : BaseView {
|
||||
fun openSystemSettings()
|
||||
|
||||
fun enableNotification(notificationKey: String, enable: Boolean)
|
||||
|
||||
fun openNotificationPermissionDialog()
|
||||
|
||||
fun setNotificationPiggybackPreferenceChecked(isChecked: Boolean)
|
||||
}
|
||||
|
Reference in New Issue
Block a user