/* * Copyright (C) 2023 MURENA SAS * 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 . */ package foundation.e.advancedprivacy import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context import androidx.annotation.StringRes import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import foundation.e.advancedprivacy.core.utils.notificationBuilder import foundation.e.advancedprivacy.domain.entities.CHANNEL_FAKE_LOCATION_FLAG import foundation.e.advancedprivacy.domain.entities.CHANNEL_FIRST_BOOT import foundation.e.advancedprivacy.domain.entities.CHANNEL_IPSCRAMBLING_FLAG import foundation.e.advancedprivacy.domain.entities.CHANNEL_TRACKER_FLAG import foundation.e.advancedprivacy.domain.entities.FeatureState import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_FAKE_LOCATION_FLAG import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_FIRST_BOOT import foundation.e.advancedprivacy.domain.entities.NOTIFICATION_IPSCRAMBLING_FLAG import foundation.e.advancedprivacy.domain.entities.NotificationContent import foundation.e.advancedprivacy.domain.usecases.GetQuickPrivacyStateUseCase import foundation.e.advancedprivacy.externalinterfaces.permissions.IPermissionsPrivacyModule import foundation.e.advancedprivacy.main.MainActivity 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 { 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, pendingIntent = MainActivity.deepLinkBuilder(context) .setDestination(R.id.dashboardFragment) .createPendingIntent() ) ) .setAutoCancel(true) NotificationManagerCompat.from(context).notify( NOTIFICATION_FIRST_BOOT, notificationBuilder.build() ) } fun startListening( appContext: Context, getQuickPrivacyStateUseCase: GetQuickPrivacyStateUseCase, permissionsPrivacyModule: IPermissionsPrivacyModule, 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 ) createNotificationFlagChannel( context = appContext, permissionsPrivacyModule = permissionsPrivacyModule, channelId = CHANNEL_TRACKER_FLAG, channelName = R.string.notifications_tracker_channel_name, channelDescription = R.string.notifications_ipscrambling_channel_description ) getQuickPrivacyStateUseCase.isLocationHidden.onEach { if (it) { showFlagNotification(appContext, NOTIFICATION_FAKE_LOCATION_FLAG) } else { hideFlagNotification(appContext, NOTIFICATION_FAKE_LOCATION_FLAG) } }.launchIn(appScope) getQuickPrivacyStateUseCase.ipScramblingMode.map { it != FeatureState.OFF }.distinctUntilChanged().onEach { if (it) { showFlagNotification(appContext, NOTIFICATION_IPSCRAMBLING_FLAG) } else { hideFlagNotification(appContext, NOTIFICATION_IPSCRAMBLING_FLAG) } }.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: IPermissionsPrivacyModule, 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, id: Int) { when (id) { NOTIFICATION_FAKE_LOCATION_FLAG -> 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, pendingIntent = MainActivity.deepLinkBuilder(context) .addDestination(R.id.fakeLocationFragment) .createPendingIntent() ) ) NOTIFICATION_IPSCRAMBLING_FLAG -> 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, pendingIntent = MainActivity.deepLinkBuilder(context) .addDestination(R.id.internetPrivacyFragment) .createPendingIntent() ) ) 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, id: Int) { NotificationManagerCompat.from(context).cancel(id) } }