Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import com.mindful.android.helpers.device.NotificationHelper
import com.mindful.android.helpers.device.PermissionsHelper
import com.mindful.android.helpers.storage.SharedPrefsHelper
import com.mindful.android.helpers.usages.AppsUsageHelper.getAppsUsageForInterval
import com.mindful.android.models.TimeTracker
import com.mindful.android.models.WebRestriction
import com.mindful.android.models.AppRestriction
import com.mindful.android.models.BedtimeSchedule
import com.mindful.android.models.FocusSession
Expand Down Expand Up @@ -132,13 +134,30 @@ class FgMethodCallHandler(
)
}

"getWebTimeSpent" -> {
val timeTrackers = trackerServiceConn.service?.getRestrictionManager?.getWebTimeTrackers
?: mapOf<String, TimeTracker>()
val host = call.arguments() ?: ""
val timetracker = timeTrackers.getOrDefault(host, TimeTracker())
result.success(
timetracker.timeSpent
)
}

"getAppsLaunchCount" -> {
result.success(
trackerServiceConn.service?.getRestrictionManager?.getAppsLaunchCount
?: mapOf<String, Int>()
)
}

"getWebLaunchCount" -> {
result.success(
trackerServiceConn.service?.getRestrictionManager?.getWebLaunchCount
?: mapOf<String, Int>()
)
}

"getShortsScreenTimeMs" -> {
result.success(SharedPrefsHelper.getSetShortsScreenTimeMs(context, null))
}
Expand All @@ -155,20 +174,27 @@ class FgMethodCallHandler(
// ==============================================================================================================
// ====================================== SERVICES =================================================================
// ==============================================================================================================
"updateWebRestrictions" -> {
val webRestrictions = JsonUtils.parseWebRestrictionsMap(
call.arguments() ?: ""
)
updateTrackerServiceRestrictions(webRestrictions, null, null)
result.success(true)
}

"updateAppRestrictions" -> {
val appRestrictions = JsonUtils.parseAppRestrictionsMap(
call.arguments() ?: ""
)
updateTrackerServiceRestrictions(appRestrictions, null)
updateTrackerServiceRestrictions(null, appRestrictions, null)
result.success(true)
}

"updateRestrictionsGroups" -> {
val restrictionGroups = JsonUtils.parseRestrictionGroupsMap(
call.arguments() ?: ""
)
updateTrackerServiceRestrictions(null, restrictionGroups)
updateTrackerServiceRestrictions(null, null, restrictionGroups)
result.success(true)
}

Expand Down Expand Up @@ -446,17 +472,20 @@ class FgMethodCallHandler(
* or null if only app-specific restrictions are being updated.
*/
private fun updateTrackerServiceRestrictions(
webRestrictions: HashMap<String, WebRestriction>?,
appRestrictions: HashMap<String, AppRestriction>?,
restrictionGroups: HashMap<Int, RestrictionGroup>?,
) {
if (trackerServiceConn.isActive) {
trackerServiceConn.service?.getRestrictionManager?.updateRestrictions(
webRestrictions,
appRestrictions,
restrictionGroups
)
} else if (appRestrictions?.isNotEmpty() == true || restrictionGroups?.isNotEmpty() == true) {
trackerServiceConn.setOnConnectedCallback { service ->
service.getRestrictionManager.updateRestrictions(
webRestrictions,
appRestrictions,
restrictionGroups
)
Expand All @@ -479,4 +508,4 @@ class FgMethodCallHandler(
return intent == null
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ enum class RestrictionType {
FOCUS,
BEDTIME,
LAUNCH_COUNT,
WEB_TIMER,
WEB_ACTIVE_PERIOD,
APP_TIMER,
APP_ACTIVE_PERIOD,
GROUP_TIMER,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.mindful.android.models

import com.mindful.android.enums.ReminderType
import com.mindful.android.enums.RestrictionType


data class TimeTracker(
var timeSpent: Long = 0L,
var lastTime: Long = 0L,
var maxAllowedInterval: Long = 30L * 1000L
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.mindful.android.models

import android.util.Log
import com.mindful.android.enums.ReminderType
import org.json.JSONObject

/**
* Represents app-level restriction configuration, such as usage time and access limits.
*/
data class WebRestriction(
/**
* website host.
*/
val host: String = "",

/**
* Daily timer limit for the app, in seconds.
*/
val timerSec: Int = 0,

/**
* Launch limit per day.
*/
val launchLimit: Int = 0,

/**
* Time of day (in minutes) from midnight when the app usage is allowed to start.
*/
val activePeriodStart: Int = 0,

/**
* Time of day (in minutes) from midnight when the app usage is blocked.
*/
val activePeriodEnd: Int = 0,

/**
* Type of usage reminders to show while using timed app.
*/
val reminderType: ReminderType = ReminderType.NOTIFICATION,

/**
* Flag to know if is Nsfw
*/
val isNsfw: Boolean = false,

/**
* ID of the restriction group this app belongs to (nullable).
*/
val associatedGroupId: Int? = null,
) {
companion object {
/**
* Constructs an [AppRestriction] from a JSON string.
*/
fun fromJson(json: String): WebRestriction {
val jsonObject = JSONObject(json)
return WebRestriction(
host = jsonObject.optString("host", ""),
timerSec = jsonObject.optInt("timerSec", 0),
launchLimit = jsonObject.optInt("launchLimit", 0),
activePeriodStart = jsonObject.optInt("activePeriodStart", 0),
activePeriodEnd = jsonObject.optInt("activePeriodEnd", 0),
isNsfw = jsonObject.optBoolean("isNsfw", false),
reminderType = ReminderType.fromName(jsonObject.optString("reminderType", "toast")),
associatedGroupId = if (jsonObject.isNull("associatedGroupId")) null else jsonObject.optInt(
"associatedGroupId"
),
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import android.util.Log
import com.mindful.android.helpers.storage.SharedPrefsHelper
import com.mindful.android.services.accessibility.TrackingManager.Companion.ACTION_ACCESSIBILITY_ACTIVE
import com.mindful.android.services.accessibility.TrackingManager.Companion.ACTION_ACCESSIBILITY_INACTIVE
import com.mindful.android.services.accessibility.TrackingManager.Companion.ACTION_NEW_WEB_EVENT
import com.mindful.android.services.accessibility.TrackingManager.Companion.ACTION_NEW_APP_LAUNCHED
import com.mindful.android.services.accessibility.TrackingManager.Companion.EXTRA_PACKAGE_NAME
import com.mindful.android.services.accessibility.TrackingManager.Companion.EXTRA_HOST_NAME
import com.mindful.android.utils.Utils

class AccessibilityReceiver(
private val onServiceStatusChanged: ((isActive: Boolean) -> Unit)? = null,
private val onNewWebEvent: ((host: String) -> Unit)? = null,
private val onNewAppLaunched: ((packageName: String) -> Unit)? = null,

) : BroadcastReceiver() {
Expand All @@ -28,6 +31,7 @@ class AccessibilityReceiver(
IntentFilter().apply {
addAction(ACTION_ACCESSIBILITY_ACTIVE)
addAction(ACTION_ACCESSIBILITY_INACTIVE)
addAction(ACTION_NEW_WEB_EVENT)
addAction(ACTION_NEW_APP_LAUNCHED)
},
)
Expand All @@ -51,6 +55,10 @@ class AccessibilityReceiver(
when (it.action) {
ACTION_ACCESSIBILITY_ACTIVE -> onServiceStatusChanged?.invoke(true)
ACTION_ACCESSIBILITY_INACTIVE -> onServiceStatusChanged?.invoke(false)
ACTION_NEW_WEB_EVENT -> it.getStringExtra(EXTRA_HOST_NAME)
?.let { host ->
onNewWebEvent?.invoke(host)
}
ACTION_NEW_APP_LAUNCHED -> it.getStringExtra(EXTRA_PACKAGE_NAME)
?.let { packageName ->
onNewAppLaunched?.invoke(packageName)
Expand All @@ -60,4 +68,4 @@ class AccessibilityReceiver(
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.mindful.android.receivers

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.util.Log
import com.mindful.android.helpers.storage.SharedPrefsHelper
import com.mindful.android.utils.Utils
import com.mindful.android.services.accessibility.MindfulAccessibilityService.Companion.ACTION_PERFORM_HOME_PRESS
import com.mindful.android.services.accessibility.MindfulAccessibilityService.Companion.ACTION_PERFORM_BACK_PRESS

class GeneralReceiver(
private val goHomeWithToast: (() -> Unit)? = null,
private val goBackWithToast: (() -> Unit)? = null,
) : BroadcastReceiver() {

private val TAG = "Mindful.GeneralReceiver"

fun register(context: Context) {
try {
Utils.safelyRegisterReceiver(
context,
this,
IntentFilter().apply {
addAction(ACTION_PERFORM_HOME_PRESS)
addAction(ACTION_PERFORM_BACK_PRESS)
},
)
} catch (e: Exception) {
Log.e(TAG, "register: Failed to register receiver", e)
SharedPrefsHelper.insertCrashLogToPrefs(context, e)
}
}

fun unRegister(context: Context) {
try {
context.unregisterReceiver(this)
} catch (e: Exception) {
Log.e(TAG, "register: Failed to un-register receiver", e)
SharedPrefsHelper.insertCrashLogToPrefs(context, e)
}
}

override fun onReceive(context: Context?, intent: Intent?) {
intent?.let {
when (it.action) {
ACTION_PERFORM_HOME_PRESS -> goHomeWithToast?.invoke()
ACTION_PERFORM_BACK_PRESS -> goBackWithToast?.invoke()
else -> return
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ class BrowserManager(
private var mLastRedirectedUrl = ""
private val throttler: Throttler = Throttler(1000L)

fun getHost(packageName: String, node: AccessibilityNodeInfo): String?
{
var url = extractBrowserUrl(node, packageName)
if (url.contains(" ") || !url.contains(".")) return null
url = url.replace("google.com/amp/s/amp.", "")
val host = Utils.parseHostNameFromUrl(url) ?: return null
return host
}

/**
* Blocks access to websites and short-form content based on current settings.
Expand All @@ -38,20 +46,10 @@ class BrowserManager(
wellbeing: Wellbeing,
) {
var url = extractBrowserUrl(node, packageName)

// Return if url is empty or does not contain dot or have space this basically means its not url
if (url.contains(" ") || !url.contains(".")) return

// Clean google AMP from the url if found (some site can appear in the AMP container with google's amp domain)
url = url.replace("google.com/amp/s/amp.", "")

// Block websites
val host = Utils.parseHostNameFromUrl(url) ?: return
val host = getHost(packageName, node) ?: return

when {
wellbeing.blockedWebsites.contains(host)
|| wellbeing.nsfwWebsites.contains(host)
|| nsfwDomains[host] ?: false
nsfwDomains[host] ?: false
-> {
Log.d(TAG, "blockDistraction: Blocked website $host opened in $packageName")
blockedContentGoBack.invoke()
Expand Down Expand Up @@ -222,4 +220,4 @@ class BrowserManager(
return ""
}
}
}
}
Loading