Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9bf4fe67 authored by Nishith  Khanna's avatar Nishith Khanna
Browse files

Merge branch '3065-reports_calls_and_leaks' into 'main'

3065 reports calls and leaks

See merge request !191
parents 3ad8c31d 45e244e0
Loading
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -215,7 +215,6 @@ class NotificationsPresenter(
            .setColorized(true)
            .setSmallIcon(R.drawable.ic_advanced_privacy_for_notification)

        notificationBuilder.setSmallIcon(R.drawable.ic_shield_alert)
        notificationBuilder.setAutoCancel(true)

        val goToTrackersIntent = MainActivity.deepLinkBuilder(context)
+17 −7
Original line number Diff line number Diff line
@@ -238,17 +238,27 @@ class WeeklyReportUseCase(
        }
    }

    private fun addCallAndLeaksCandidates(candidates: MutableList<WeeklyReport>, endOfWeek: Instant) {
        val blockedRate = Random.nextInt(100).toString()
        val leaks = Random.nextInt(1000).toString()
    private suspend fun addCallAndLeaksCandidates(candidates: MutableList<WeeklyReport>, endOfWeek: Instant) {
        val startOfWeek = endOfWeek.minus(7, ChronoUnit.DAYS)
        val (calls, leaks) = statsDatabase.getCallsAndLeaks(startOfWeek, endOfWeek)

        if (calls == 0) {
            return
        }

        val blockedLeaks = calls - leaks
        val blockedRate = blockedLeaks * 100 / calls

        val blockedRateStr = blockedRate.toString()
        val blockedLeaksStr = blockedLeaks.toString()

        candidates.add(
            WeeklyReport(
                endOfWeek,
                WeeklyReport.StatType.CALLS_AND_LEAKS,
                WeeklyReport.LabelId.CALLS_AND_LEAKS_1,
                blockedRate,
                listOf(leaks)
                blockedRateStr,
                listOf(blockedLeaksStr)
            )
        )
        candidates.add(
@@ -256,8 +266,8 @@ class WeeklyReportUseCase(
                endOfWeek,
                WeeklyReport.StatType.CALLS_AND_LEAKS,
                WeeklyReport.LabelId.CALLS_AND_LEAKS_2,
                blockedRate,
                listOf(leaks)
                blockedRateStr,
                listOf(blockedLeaksStr)
            )
        )
    }
+135 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 E FOUNDATION
 *
 * 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.features.weeklyreport

import android.content.Context
import android.content.res.ColorStateList
import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import foundation.e.advancedprivacy.R
import foundation.e.advancedprivacy.databinding.WeeklyreportItemCallsAndLeaksBinding
import foundation.e.advancedprivacy.domain.entities.weeklyreport.DisplayableReport
import foundation.e.advancedprivacy.domain.entities.weeklyreport.WeeklyReport

class CallsAndLeaksViewFactory(private val context: Context) {
    fun getShareTitle(): CharSequence {
        return context.getString(R.string.weeklyreport_call_and_leaks_share_title)
    }

    fun createView(report: DisplayableReport, inflater: LayoutInflater, viewGroup: ViewGroup): View {
        val binding = WeeklyreportItemCallsAndLeaksBinding.inflate(inflater, viewGroup, false)

        val labelId = report.report.labelId
        binding.title.text = getTitle(report, false)
        binding.primaryValue.text = context.getString(R.string.weeklyreport_label_call_and_leaks_primaryvalue, report.report.primaryValue)
        binding.description1.text = when (labelId) {
            WeeklyReport.LabelId.CALLS_AND_LEAKS_1 ->
                context.getString(R.string.weeklyreport_label_call_and_leaks_1_description_1)
            WeeklyReport.LabelId.CALLS_AND_LEAKS_2 ->
                context.getString(R.string.weeklyreport_label_call_and_leaks_2_description_1, report.report.primaryValue)
            else -> ""
        }

        binding.secondaryValue.text = context.getString(
            R.string.weeklyreport_label_call_and_leaks_secondaryvalue,
            report.report.secondaryValues.firstOrNull()
        )

        binding.description2.setText(
            when (labelId) {
                WeeklyReport.LabelId.CALLS_AND_LEAKS_1 -> R.string.weeklyreport_label_call_and_leaks_1_description_2
                WeeklyReport.LabelId.CALLS_AND_LEAKS_2 -> R.string.weeklyreport_label_call_and_leaks_2_description_2
                else -> R.string.empty
            }
        )

        return binding.root
    }

    fun createViewForSharing(report: DisplayableReport, inflater: LayoutInflater, viewGroup: ViewGroup): View {
        val binding = WeeklyreportItemCallsAndLeaksBinding.inflate(inflater, viewGroup, false)

        val labelId = report.report.labelId
        binding.title.text = getTitle(report, true)
        binding.primaryValue.text = context.getString(R.string.weeklyreport_label_call_and_leaks_primaryvalue, report.report.primaryValue)
        binding.description1.text = when (labelId) {
            WeeklyReport.LabelId.CALLS_AND_LEAKS_1 ->
                context.getString(R.string.weeklyreport_label_call_and_leaks_1_description_1_sharing)
            WeeklyReport.LabelId.CALLS_AND_LEAKS_2 ->
                context.getString(R.string.weeklyreport_label_call_and_leaks_2_description_sharing, report.report.primaryValue)
            else -> ""
        }

        binding.secondaryValue.text = context.getString(
            R.string.weeklyreport_label_call_and_leaks_secondaryvalue_sharing,
            report.report.secondaryValues.firstOrNull()
        )

        binding.description2.setText(
            when (labelId) {
                WeeklyReport.LabelId.CALLS_AND_LEAKS_1 -> R.string.weeklyreport_label_call_and_leaks_1_description_2
                WeeklyReport.LabelId.CALLS_AND_LEAKS_2 -> R.string.weeklyreport_label_call_and_leaks_2_description_2
                else -> R.string.empty
            }
        )

        with(binding.secondaryValue) {
            backgroundTintList =
                ColorStateList.valueOf(ContextCompat.getColor(context, R.color.share_blue_highlight_number))
            setTextColor(ContextCompat.getColor(context, R.color.white))

            if (labelId == WeeklyReport.LabelId.CALLS_AND_LEAKS_2) {
                binding.description2.isVisible = false
            }
        }

        return binding.root
    }

    fun getTitle(report: DisplayableReport, forSharing: Boolean = false): CharSequence {
        val labelId = report.report.labelId
        return context.getString(
            when {
                labelId == WeeklyReport.LabelId.CALLS_AND_LEAKS_1 -> R.string.weeklyreport_label_call_and_leaks_1_title
                labelId == WeeklyReport.LabelId.CALLS_AND_LEAKS_2 && forSharing ->
                    R.string.weeklyreport_label_call_and_leaks_2_title_sharing
                labelId == WeeklyReport.LabelId.CALLS_AND_LEAKS_2 ->
                    R.string.weeklyreport_label_call_and_leaks_2_title
                else ->
                    R.string.empty
            }
        )
    }

    fun getDescriptionForNotification(report: DisplayableReport): String {
        val descriptionId = when (report.report.labelId) {
            WeeklyReport.LabelId.CALLS_AND_LEAKS_1 -> R.string.weeklyreport_label_call_and_leaks_1_description_notification
            WeeklyReport.LabelId.CALLS_AND_LEAKS_2 -> R.string.weeklyreport_label_call_and_leaks_2_description_notification
            else ->
                R.string.empty
        }

        return context.getString(descriptionId, report.report.primaryValue, *report.report.secondaryValues.toTypedArray())
    }

    fun getIconForNotification(): Drawable? = null
}
+14 −1
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import foundation.e.advancedprivacy.domain.entities.weeklyreport.DisplayableRepo
import foundation.e.advancedprivacy.domain.entities.weeklyreport.WeeklyReport

class WeeklyReportViewFactory(private val context: Context) {
    val callsAndLeaksViewFactory: CallsAndLeaksViewFactory by lazy { CallsAndLeaksViewFactory(context) }
    val newTrackersViewFactory: NewTrackersViewFactory by lazy { NewTrackersViewFactory(context) }
    val trackerWithMostAppsViewFactory: TrackerWithMostAppsViewFactory by lazy { TrackerWithMostAppsViewFactory(context) }
    val callsPerAppViewFactory: CallsPerAppViewFactory by lazy { CallsPerAppViewFactory(context) }
@@ -48,6 +49,8 @@ class WeeklyReportViewFactory(private val context: Context) {
                trackerWithMostAppsViewFactory.getShareTitle()
            WeeklyReport.StatType.CALLS_PER_APP ->
                callsPerAppViewFactory.getShareTitle()
            WeeklyReport.StatType.CALLS_AND_LEAKS ->
                callsAndLeaksViewFactory.getShareTitle()
            else -> context.getString(R.string.weeklyreport_share_title_base)
        }
    }
@@ -60,6 +63,9 @@ class WeeklyReportViewFactory(private val context: Context) {
                trackerWithMostAppsViewFactory.createView(report, inflater, viewGroup, onClick)
            WeeklyReport.StatType.CALLS_PER_APP ->
                callsPerAppViewFactory.createView(report, inflater, viewGroup)
            WeeklyReport.StatType.CALLS_AND_LEAKS ->
                callsAndLeaksViewFactory.createView(report, inflater, viewGroup)

            else -> null
        } ?: createDefaultView(report, inflater, viewGroup)
    }
@@ -116,7 +122,8 @@ class WeeklyReportViewFactory(private val context: Context) {
                trackerWithMostAppsViewFactory.createViewForSharing(report, inflater, viewGroup)
            WeeklyReport.StatType.CALLS_PER_APP ->
                callsPerAppViewFactory.createViewForSharing(report, inflater, viewGroup)

            WeeklyReport.StatType.CALLS_AND_LEAKS ->
                callsAndLeaksViewFactory.createViewForSharing(report, inflater, viewGroup)
            else -> null
        } ?: createDefaultView(report, inflater, viewGroup)
    }
@@ -139,6 +146,8 @@ class WeeklyReportViewFactory(private val context: Context) {
            WeeklyReport.StatType.CALLS_PER_APP ->
                callsPerAppViewFactory.getTitle(report)

            WeeklyReport.StatType.CALLS_AND_LEAKS ->
                callsAndLeaksViewFactory.getTitle(report)
            else -> report.report.labelId.name
        }
    }
@@ -151,6 +160,8 @@ class WeeklyReportViewFactory(private val context: Context) {
                trackerWithMostAppsViewFactory.getDescriptionForNotification(report)
            WeeklyReport.StatType.CALLS_PER_APP ->
                callsPerAppViewFactory.getDescriptionForNotification(report)
            WeeklyReport.StatType.CALLS_AND_LEAKS ->
                callsAndLeaksViewFactory.getDescriptionForNotification(report)

            else -> getDefaultDescription(report).toString()
        }
@@ -174,6 +185,8 @@ class WeeklyReportViewFactory(private val context: Context) {
                trackerWithMostAppsViewFactory.getIconForNotification()
            WeeklyReport.StatType.CALLS_PER_APP ->
                callsPerAppViewFactory.getIconForNotification(report)
            WeeklyReport.StatType.CALLS_AND_LEAKS ->
                callsAndLeaksViewFactory.getIconForNotification()
            else -> null
        }
    }
+96 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?><!--
  ~ Copyright (C) 2025 E FOUNDATION
  ~
  ~ 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/>.
  -->

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:gravity="center_horizontal"
    android:padding="12dp"
    android:background="@drawable/bg_stroke_rounded_12">
    >
    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textSize="14sp"
        android:lineHeight="20dp"
        android:textFontWeight="400"
        android:textColor="@color/green_valid"
        android:textAllCaps="true"
        tools:text="@string/weeklyreport_label_call_and_leaks_1_title"
        />
    <TextView
        android:id="@+id/primaryValue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:textSize="24sp"
        android:lineHeight="24dp"
        android:textFontWeight="400"
        android:textColor="@color/primary_text"
        tools:text="78%"
        />
    <TextView
        android:id="@+id/description_1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:gravity="center"
        android:paddingHorizontal="16dp"
        android:textSize="12sp"
        android:lineHeight="16sp"
        android:textFontWeight="400"
        android:textColor="@color/primary_text"
        tools:text="@string/weeklyreport_label_call_and_leaks_2_description_sharing"
        />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="4dp"
        >

    <TextView
        android:id="@+id/secondary_value"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="12sp"
        android:lineHeight="16sp"
        android:textFontWeight="400"
        android:textColor="@color/secondary_text"
        android:background="@drawable/bg_tag"
        android:backgroundTint="@color/divider"
        android:paddingHorizontal="8dp"
        tools:text="1200 leaks"
        />

    <TextView
        android:id="@+id/description_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="4dp"
        android:textSize="12sp"
        android:lineHeight="16sp"
        android:textFontWeight="400"
        android:textColor="@color/primary_text"
        tools:text="@string/weeklyreport_label_call_and_leaks_1_description_2"
        />
    </LinearLayout>
</LinearLayout>
 No newline at end of file
Loading