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

Commit 01b95974 authored by Guillaume Jacquart's avatar Guillaume Jacquart
Browse files

feat:2995: Add share report.

parent 5bba7563
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
    Copyright  (C) 2022 ECORP, 2022 MURENA SAS
    Copyright  (C) 2022 - 2025 MURENA SAS
    Copyright  (C) 2022 ECORP

    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
@@ -57,6 +58,15 @@
            android:enabled="true"
            android:exported="true"
            />
        <provider
            android:name=".externalinterfaces.contentproviders.ScreenshotsProvider"
            android:authorities="foundation.e.advancedprivacy.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/fileprovider_paths" />
        </provider>


        <receiver
            android:name="foundation.e.advancedprivacy.common.BootCompletedReceiver"
+24 −14
Original line number Diff line number Diff line
@@ -44,28 +44,38 @@ class WeeklyReportUseCase(
) {
    private val _showWeeklyReportNotification = MutableSharedFlow<String>()
    val showWeeklyReportNotification: SharedFlow<String> = _showWeeklyReportNotification.asSharedFlow()

    suspend fun updateWeeklyReport() = withContext(Dispatchers.IO) {
        val weeklyReport = computeWeeklyReport(Instant.now())
        weeklyReportRepository.setLastWeeklyReport(weeklyReport)
        buildLabel(weeklyReport)?.let {
            _showWeeklyReportNotification.emit(it)
        }
    }

    suspend fun getLast(): WeeklyReport {
        return weeklyReportRepository.getLastWeeklyReport()
            ?: WeeklyReport(emptyList(), emptyList(), emptyList())
    }

    suspend fun getLastLabel(): String? {
        return buildLabel(getLast())
    }

    private fun buildLabel(weeklyReport: WeeklyReport?): String? {
        if (weeklyReport == null) return null

        val (appLabel, appTracker) =
            weeklyReport.appsWithNewTrackers.firstOrNull()?.let {
                it.app.label to it.trackers.firstOrNull()?.label
            } ?: (null to null)
            } ?: return null

        _showWeeklyReportNotification.emit(
            resourcesRepository.getString(
        return resourcesRepository.getString(
            R.string.weeklyreport_notification_description,
            appLabel,
            appTracker,
            weeklyReport.newTrackers.firstOrNull()?.label
        )
        )
    }

    suspend fun getLastWeeklyReport(): WeeklyReport {
        return weeklyReportRepository.getLastWeeklyReport()
            ?: WeeklyReport(emptyList(), emptyList(), emptyList())
    }

    suspend fun computeWeeklyReport(endOfWeek: Instant): WeeklyReport = withContext(Dispatchers.IO) {
+57 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.externalinterfaces.contentproviders

import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import androidx.core.content.FileProvider
import java.io.File

// Subclass (empty) of FileProvider, as advicsed in documentation
// https://developer.android.com/reference/androidx/core/content/FileProvider :
// "It is possible to use FileProvider directly instead of extending it. However, this is
// not reliable and will causes crashes on some devices."
class ScreenshotsProvider : FileProvider() {

    companion object {
        const val AUTHORITY = "foundation.e.advancedprivacy.fileprovider"
        private const val PATH_WEEKLYREPORTS = "weeklyreports"

        fun getSendIntentForDrawable(context: Context, bmp: Bitmap, message: String): Intent {
            val baseDir = File(context.cacheDir, PATH_WEEKLYREPORTS)
            baseDir.mkdirs()
            val screenshotOutputFile = File(baseDir, "lastreport.png")
            screenshotOutputFile.delete()

            val screenshotOutputStream = screenshotOutputFile.outputStream()
            bmp.compress(Bitmap.CompressFormat.PNG, 100, screenshotOutputStream)
            screenshotOutputStream.close()

            val contentUri = getUriForFile(context, AUTHORITY, screenshotOutputFile)

            return Intent().apply {
                action = Intent.ACTION_SEND
                flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
                setDataAndType(contentUri, "image/png")
                putExtra(Intent.EXTRA_TEXT, message)
                putExtra(Intent.EXTRA_STREAM, contentUri)
            }
        }
    }
}
+8 −1
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023-2024 MURENA SAS
 * Copyright (C) 2023 - 2025 MURENA SAS
 * Copyright (C) 2021 E FOUNDATION
 *
 * This program is free software: you can redistribute it and/or modify
@@ -193,6 +193,13 @@ class DashboardFragment : NavToolbarFragment(R.layout.fragment_dashboard) {
    }

    private fun render(state: DashboardState) {
        binding.weeklyreportLabel.text = state.weeklyReportLabel

//        (state.weeklyReportLabel != null).let {
//            binding.weeklyreportLabel.isVisible = it
//            binding.viewWeeklyreport.isVisible = it
//        }

        binding.dataBlockedTrackers.number.text = numberFormatter.format(state.blockedCallsCount)
        binding.dataApps.number.text = state.appsWithCallsCount.toString()

+3 −2
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 MURENA SAS
 * Copyright (C) 2024 - 2025 MURENA SAS
 * Copyright (C) 2022 E FOUNDATION
 *
 * This program is free software: you can redistribute it and/or modify
@@ -30,5 +30,6 @@ data class DashboardState(
    val blockedCallsCount: Int = 0,
    val appsWithCallsCount: Int = 0,
    val shameApps: List<AppWithCount> = emptyList(),
    val shameTrackers: List<TrackerWithCount> = emptyList()
    val shameTrackers: List<TrackerWithCount> = emptyList(),
    val weeklyReportLabel: String? = null
)
Loading