aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt
diff options
context:
space:
mode:
authorGuillaume Jacquart <guillaume.jacquart@hoodbrains.com>2023-05-09 06:00:43 +0000
committerGuillaume Jacquart <guillaume.jacquart@hoodbrains.com>2023-05-09 06:00:43 +0000
commit5a432ecde520ee039786848296e5227571404158 (patch)
tree077eafb42d5d2d18b2ffc03bc93d9a8654377774 /app/src/main/java/foundation/e/advancedprivacy/Notifications.kt
parenta348c8196a643e4f5853587133b05e3ec2cd0faa (diff)
parenta8874167f663885f2d3371801cf03681576ac817 (diff)
downloadadvanced-privacy-5a432ecde520ee039786848296e5227571404158.tar.gz
Merge branch '1200-move_package_to_advanced_privacy' into 'main'
1200: rename everything to AdvancedPrivacy See merge request e/os/advanced-privacy!128
Diffstat (limited to 'app/src/main/java/foundation/e/advancedprivacy/Notifications.kt')
-rw-r--r--app/src/main/java/foundation/e/advancedprivacy/Notifications.kt210
1 files changed, 210 insertions, 0 deletions
diff --git a/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt b/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt
new file mode 100644
index 0000000..68c4bd3
--- /dev/null
+++ b/app/src/main/java/foundation/e/advancedprivacy/Notifications.kt
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2022 MURENA SAS
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package foundation.e.advancedprivacy
+
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import androidx.annotation.StringRes
+import androidx.core.app.NotificationCompat
+import androidx.core.app.NotificationManagerCompat
+import foundation.e.advancedprivacy.domain.entities.InternetPrivacyMode
+import foundation.e.advancedprivacy.domain.entities.MainFeatures
+import foundation.e.advancedprivacy.domain.usecases.GetQuickPrivacyStateUseCase
+import foundation.e.advancedprivacy.main.MainActivity
+import foundation.e.privacymodules.permissions.PermissionsPrivacyModule
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
+
+object Notifications {
+ const val CHANNEL_FIRST_BOOT = "first_boot_notification"
+ const val CHANNEL_FAKE_LOCATION_FLAG = "fake_location_flag"
+ const val CHANNEL_IPSCRAMBLING_FLAG = "ipscrambling_flag"
+
+ const val NOTIFICATION_FIRST_BOOT = 1000
+ const val NOTIFICATION_FAKE_LOCATION_FLAG = NOTIFICATION_FIRST_BOOT + 1
+ const val NOTIFICATION_IPSCRAMBLING_FLAG = NOTIFICATION_FAKE_LOCATION_FLAG + 1
+
+ fun showFirstBootNotification(context: Context) {
+ createNotificationFirstBootChannel(context)
+ val notificationBuilder: NotificationCompat.Builder = notificationBuilder(
+ context,
+ NotificationContent(
+ channelId = CHANNEL_FIRST_BOOT,
+ icon = R.drawable.ic_notification_logo,
+ title = R.string.first_notification_title,
+ description = R.string.first_notification_summary,
+ destinationIntent =
+ context.packageManager.getLaunchIntentForPackage(context.packageName)
+ )
+ )
+ .setAutoCancel(true)
+
+ NotificationManagerCompat.from(context).notify(
+ NOTIFICATION_FIRST_BOOT, notificationBuilder.build()
+ )
+ }
+
+ fun startListening(
+ appContext: Context,
+ getQuickPrivacyStateUseCase: GetQuickPrivacyStateUseCase,
+ permissionsPrivacyModule: PermissionsPrivacyModule,
+ appScope: CoroutineScope
+ ) {
+ createNotificationFlagChannel(
+ context = appContext,
+ permissionsPrivacyModule = permissionsPrivacyModule,
+ channelId = CHANNEL_FAKE_LOCATION_FLAG,
+ channelName = R.string.notifications_fake_location_channel_name,
+ channelDescription = R.string.notifications_fake_location_channel_description
+ )
+
+ createNotificationFlagChannel(
+ context = appContext,
+ permissionsPrivacyModule = permissionsPrivacyModule,
+ channelId = CHANNEL_IPSCRAMBLING_FLAG,
+ channelName = R.string.notifications_ipscrambling_channel_name,
+ channelDescription = R.string.notifications_ipscrambling_channel_description
+ )
+
+ getQuickPrivacyStateUseCase.isLocationHidden.onEach {
+ if (it) {
+ showFlagNotification(appContext, MainFeatures.FAKE_LOCATION)
+ } else {
+ hideFlagNotification(appContext, MainFeatures.FAKE_LOCATION)
+ }
+ }.launchIn(appScope)
+
+ getQuickPrivacyStateUseCase.ipScramblingMode.map {
+ it != InternetPrivacyMode.REAL_IP
+ }.distinctUntilChanged().onEach {
+ if (it) {
+ showFlagNotification(appContext, MainFeatures.IP_SCRAMBLING)
+ } else {
+ hideFlagNotification(appContext, MainFeatures.IP_SCRAMBLING)
+ }
+ }.launchIn(appScope)
+ }
+
+ private fun createNotificationFirstBootChannel(context: Context) {
+ val channel = NotificationChannel(
+ CHANNEL_FIRST_BOOT,
+ context.getString(R.string.notifications_first_boot_channel_name),
+ NotificationManager.IMPORTANCE_HIGH
+ )
+ NotificationManagerCompat.from(context).createNotificationChannel(channel)
+ }
+
+ private fun createNotificationFlagChannel(
+ context: Context,
+ permissionsPrivacyModule: PermissionsPrivacyModule,
+ channelId: String,
+ @StringRes channelName: Int,
+ @StringRes channelDescription: Int,
+ ) {
+ val channel = NotificationChannel(
+ channelId, context.getString(channelName), NotificationManager.IMPORTANCE_LOW
+ )
+ channel.description = context.getString(channelDescription)
+ permissionsPrivacyModule.setBlockable(channel)
+ NotificationManagerCompat.from(context).createNotificationChannel(channel)
+ }
+
+ private fun showFlagNotification(context: Context, feature: MainFeatures) {
+ when (feature) {
+ MainFeatures.FAKE_LOCATION -> showFlagNotification(
+ context = context,
+ id = NOTIFICATION_FAKE_LOCATION_FLAG,
+ content = NotificationContent(
+ channelId = CHANNEL_FAKE_LOCATION_FLAG,
+ icon = R.drawable.ic_fmd_bad,
+ title = R.string.notifications_fake_location_title,
+ description = R.string.notifications_fake_location_content,
+ destinationIntent = MainActivity.createFakeLocationIntent(context),
+ )
+ )
+ MainFeatures.IP_SCRAMBLING -> showFlagNotification(
+ context = context,
+ id = NOTIFICATION_IPSCRAMBLING_FLAG,
+ content = NotificationContent(
+ channelId = CHANNEL_IPSCRAMBLING_FLAG,
+ icon = R.drawable.ic_language,
+ title = R.string.notifications_ipscrambling_title,
+ description = R.string.notifications_ipscrambling_content,
+ destinationIntent = MainActivity.createIpScramblingIntent(context),
+ )
+ )
+ else -> {}
+ }
+ }
+
+ private fun showFlagNotification(
+ context: Context,
+ id: Int,
+ content: NotificationContent,
+ ) {
+ val builder = notificationBuilder(context, content)
+ .setPriority(NotificationCompat.PRIORITY_LOW)
+ .setOngoing(true)
+
+ NotificationManagerCompat.from(context).notify(id, builder.build())
+ }
+
+ private fun hideFlagNotification(context: Context, feature: MainFeatures) {
+ val id = when (feature) {
+ MainFeatures.FAKE_LOCATION -> NOTIFICATION_FAKE_LOCATION_FLAG
+ MainFeatures.IP_SCRAMBLING -> NOTIFICATION_IPSCRAMBLING_FLAG
+ else -> return
+ }
+ NotificationManagerCompat.from(context).cancel(id)
+ }
+
+ private data class NotificationContent(
+ val channelId: String,
+ val icon: Int,
+ val title: Int,
+ val description: Int,
+ val destinationIntent: Intent?
+ )
+
+ private fun notificationBuilder(
+ context: Context,
+ content: NotificationContent
+ ): NotificationCompat.Builder {
+ val builder = NotificationCompat.Builder(context, content.channelId)
+ .setSmallIcon(content.icon)
+ .setPriority(NotificationCompat.PRIORITY_LOW)
+ .setContentTitle(context.getString(content.title))
+ .setStyle(NotificationCompat.BigTextStyle().bigText(context.getString(content.description)))
+
+ content.destinationIntent?.let {
+ it.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ val pendingIntent: PendingIntent = PendingIntent.getActivity(
+ context, 0, it, PendingIntent.FLAG_IMMUTABLE
+ )
+ builder.setContentIntent(pendingIntent)
+ }
+
+ return builder
+ }
+}