1package com.peachpasswords.sync23import android.app.Notification4import android.app.NotificationChannel5import android.app.NotificationManager6import android.app.PendingIntent7import android.content.Context8import android.content.Intent9import androidx.core.app.NotificationCompat10import com.peachpasswords.MainActivity11import com.peachpasswords.R12import dagger.hilt.android.qualifiers.ApplicationContext13import javax.inject.Inject14import javax.inject.Singleton1516@Singleton17class SyncAlertStore @Inject constructor(18 @ApplicationContext private val context: Context,19) : SyncAlertRecorder {20 init {21 22 23 context.deleteSharedPreferences(LEGACY_PREFS_FILE)24 }2526 override fun record(alerts: List<SyncAlert>) {27 28 val capped = alerts.map { it.copy(deviceName = it.deviceName?.let(::capDeviceName)) }29 val content = syncSecurityNotificationContent(capped) ?: return30 val manager =31 context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager32 runCatching {33 manager.notify(34 SYNC_SECURITY_NOTIFICATION_ID,35 buildSyncSecurityNotification(context, content),36 )37 }38 }3940 fun clear() {41 val manager =42 context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager43 manager.cancel(SYNC_SECURITY_NOTIFICATION_ID)44 }45}4647internal const val SYNC_SECURITY_NOTIFICATION_CHANNEL_ID = "peach_sync_security"48internal const val SYNC_SECURITY_NOTIFICATION_ID = 420249private const val LEGACY_PREFS_FILE = "peach_sync_alerts"5051internal fun buildSyncSecurityNotification(52 context: Context,53 content: SyncSecurityNotificationContent,54): Notification {55 val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager56 manager.createNotificationChannel(57 NotificationChannel(58 SYNC_SECURITY_NOTIFICATION_CHANNEL_ID,59 "Peach Sync security",60 NotificationManager.IMPORTANCE_DEFAULT,61 ).apply {62 description = "Device removals and unexpected Peach Sync key changes."63 },64 )65 val open = PendingIntent.getActivity(66 context,67 0,68 Intent(context, MainActivity::class.java),69 PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT,70 )71 val builder = NotificationCompat.Builder(context, SYNC_SECURITY_NOTIFICATION_CHANNEL_ID)72 .setContentTitle(content.title)73 .setContentText(content.summary)74 .setSmallIcon(R.drawable.ic_launcher_monochrome)75 .setPriority(NotificationCompat.PRIORITY_DEFAULT)76 .setCategory(NotificationCompat.CATEGORY_STATUS)77 .setVisibility(NotificationCompat.VISIBILITY_PRIVATE)78 .setAutoCancel(true)79 .setContentIntent(open)8081 if (content.lines.size == 1) {82 builder.setStyle(NotificationCompat.BigTextStyle().bigText(content.summary))83 } else {84 builder.setStyle(85 NotificationCompat.InboxStyle()86 .also { style -> content.lines.takeLast(5).forEach(style::addLine) }87 .setSummaryText("${content.lines.size} device security updates"),88 )89 }9091 return builder.build()92}