Skip to content

Commit

Permalink
Merge pull request #68 from akaMrNagar/dev
Browse files Browse the repository at this point in the history
Major improvement and new features
  • Loading branch information
akaMrNagar authored Mar 2, 2025
2 parents b04459d + d698ae4 commit a5c997f
Show file tree
Hide file tree
Showing 78 changed files with 3,703 additions and 1,018 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,5 @@ Your feedback is invaluable to us! If you have suggestions, encounter issues, or

### Translation

1. Japanese by [*Riikun*](https://github.com/akaMrNagar/Mindful?tab=readme-ov-file#donate)
1. Japanese by [*Riikun*](https://crowdin.com/profile/riikun)
2. Turkish by [*Kerem*](https://crowdin.com/profile/keremk)
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:enableOnBackInvokedCallback="false"
android:enableOnBackInvokedCallback="true"
android:exported="true"
android:hardwareAccelerated="true"
android:launchMode="singleTop"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,28 @@ class FgMethodCallHandler(
) : MethodCallHandler {

private val focusServiceConn =
SafeServiceConnection(FocusSessionService::class.java, context)
SafeServiceConnection(
context = context,
serviceClass = FocusSessionService::class.java
)

private val trackerServiceConn =
SafeServiceConnection(MindfulTrackerService::class.java, context)
SafeServiceConnection(
context = context,
serviceClass = MindfulTrackerService::class.java
)

private val vpnServiceConn =
SafeServiceConnection(MindfulVpnService::class.java, context)
SafeServiceConnection(
context = context,
serviceClass = MindfulVpnService::class.java
)

private val notificationServiceConn =
SafeServiceConnection(MindfulNotificationListenerService::class.java, context)
SafeServiceConnection(
context = context,
serviceClass = MindfulNotificationListenerService::class.java
)


init {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.mindful.android.enums

/**
* Enum representing short-form content features
*/
enum class ShortsPlatformFeatures {
INSTAGRAM_REELS,
INSTAGRAM_EXPLORE,
SNAPCHAT_SPOTLIGHT,
SNAPCHAT_DISCOVER,
FACEBOOK_REELS,
REDDIT_SHORTS,
YOUTUBE_SHORTS,
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,24 @@ import com.mindful.android.utils.Utils
* @param <T> The type of Service this class is designed to connect to.</T>
*/
class SafeServiceConnection<T : Service>(
private val serviceClass: Class<T>,
private val context: Context,
private val serviceClass: Class<T>,
) : ServiceConnection {

var service: T? = null
val isActive: Boolean get() = service != null

private var mIsBound = false
private var mOnConnectedCallback: ((service: T) -> Unit)? = null;
private var mOnServiceConnected: ((service: T) -> Unit)? = null

override fun onServiceConnected(name: ComponentName, binder: IBinder) {
try {
service = (binder as ServiceBinder<T>?)?.service
val binderService = (binder as ServiceBinder<T>?)?.service

if (service != null) {
binderService?.let {
service = it
mIsBound = true
mOnConnectedCallback?.invoke(service!!)
mOnServiceConnected?.invoke(it)
}
} catch (ignored: Exception) {
}
Expand Down Expand Up @@ -125,6 +126,6 @@ class SafeServiceConnection<T : Service>(
* @param callback The callback to be triggered upon successful connection.
*/
fun setOnConnectedCallback(callback: ((service: T) -> Unit)) {
mOnConnectedCallback = callback
mOnServiceConnected = callback
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ object AlarmTasksSchedulingHelper {

// Let service know
if (Utils.isServiceRunning(context, MindfulTrackerService::class.java)) {
val conn = SafeServiceConnection(MindfulTrackerService::class.java, context)
val conn = SafeServiceConnection(context, MindfulTrackerService::class.java)
conn.setOnConnectedCallback { service ->
service.getRestrictionManager.updateBedtimeApps(
null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,14 @@
*/
package com.mindful.android.models

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

/**
* Represents the settings related to user well-being in the application.
*/
data class WellBeingSettings(private val jsonObject: JSONObject) {
/**
* Flag indicating whether to block Instagram Reels.
*/
val blockInstaReels: Boolean = jsonObject.optBoolean("blockInstaReels", false)

/**
* Flag indicating whether to block YouTube Shorts.
*/
val blockYtShorts: Boolean = jsonObject.optBoolean("blockYtShorts", false)

/**
* Flag indicating whether to block Snapchat Spotlight.
*/
val blockSnapSpotlight: Boolean = jsonObject.optBoolean("blockSnapSpotlight", false)

/**
* Flag indicating whether to block Facebook Reels.
*/
val blockFbReels: Boolean = jsonObject.optBoolean("blockFbReels", false)

/**
* Flag indicating whether to block Reddit Shorts.
*/
val blockRedditShorts: Boolean = jsonObject.optBoolean("blockRedditShorts", false)

/**
* Flag indicating whether to block NSFW or adult websites.
* This is used to determine if the accessibility service is filtering websites.
Expand All @@ -56,31 +33,42 @@ data class WellBeingSettings(private val jsonObject: JSONObject) {
jsonObject.optInt("allowedShortsTimeSec", 30 * 60) * 1000L

/**
* List of website hosts that are blocked.
* List of blocked short-form features (stored as enum indexes)
*/
val blockedWebsites: MutableList<String>
val blockedShortsPlatformFeatures: Set<ShortsPlatformFeatures>

/**
* List of website hosts that are blocked including custom nsfw websites.
*/
val blockedWebsites: Set<String>

init {
val allWebsites = mutableListOf<String>()

// Deserialize blocked websites
val websitesJsonArray = jsonObject.optJSONArray("blockedWebsites")
if (websitesJsonArray != null) {
for (i in 0 until websitesJsonArray.length()) {
allWebsites.add(websitesJsonArray.getString(i))
val blockedFeatures = mutableSetOf<ShortsPlatformFeatures>()
// Deserialize blocked shorts platform features
jsonObject.optJSONArray("blockedShortsPlatformFeatures")?.let { featuresArray ->
for (i in 0 until featuresArray.length()) {
blockedFeatures.add(ShortsPlatformFeatures.values()[featuresArray.getInt(i)])
}
}
this.blockedShortsPlatformFeatures = blockedFeatures

// Deserialize nsfw websites
val nsfwSitesJsonArray = jsonObject.optJSONArray("nsfwWebsites")
if (nsfwSitesJsonArray != null) {
for (i in 0 until nsfwSitesJsonArray.length()) {
allWebsites.add(nsfwSitesJsonArray.getString(i))

val blockedWebsites = mutableSetOf<String>()
// Deserialize blocked websites
jsonObject.optJSONArray("blockedWebsites")?.let { websitesArray ->
for (i in 0 until websitesArray.length()) {
blockedWebsites.add(websitesArray.getString(i))
}
}


this.blockedWebsites = allWebsites
// Deserialize nsfw websites
jsonObject.optJSONArray("nsfwWebsites")?.let { nsfwSitesArray ->
for (i in 0 until nsfwSitesArray.length()) {
blockedWebsites.add(nsfwSitesArray.getString(i))
}
}
this.blockedWebsites = blockedWebsites
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import android.util.Log
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkManager
import com.mindful.android.helpers.AlarmTasksSchedulingHelper
import com.mindful.android.helpers.device.NotificationHelper
Expand Down Expand Up @@ -57,6 +58,7 @@ class DeviceBootReceiver : BroadcastReceiver() {
TAG, ExistingWorkPolicy.KEEP,
OneTimeWorkRequest
.Builder(FlutterBgExecutionWorker::class.java)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.setInputData(
Data.Builder().putString(FLUTTER_TASK_ID, "onBootOrAppUpdate")
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ class BedtimeRoutineReceiver : BroadcastReceiver() {
bedtimeSettings.scheduleDays[Utils.zeroIndexedDayOfWeek()]

private val trackerServiceConn = SafeServiceConnection(
MindfulTrackerService::class.java, context
context = context,
serviceClass = MindfulTrackerService::class.java
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import android.util.Log
import androidx.work.Data
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequest
import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
Expand Down Expand Up @@ -46,6 +47,7 @@ class MidnightResetReceiver : BroadcastReceiver() {
ExistingWorkPolicy.KEEP,
OneTimeWorkRequest
.Builder(FlutterBgExecutionWorker::class.java)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.setInputData(
Data.Builder().putString(FLUTTER_TASK_ID, "onMidnightReset")
.build()
Expand All @@ -59,7 +61,8 @@ class MidnightResetReceiver : BroadcastReceiver() {
params: WorkerParameters,
) : Worker(context, params) {
private val mTrackerServiceConn = SafeServiceConnection(
MindfulTrackerService::class.java, context
context = context,
serviceClass = MindfulTrackerService::class.java,
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,19 @@ class BrowserManager(

// Block websites
val host = Utils.parseHostNameFromUrl(url)
if (settings.blockedWebsites.contains(host) || nsfwDomains.containsKey(host)) {
Log.d(TAG, "blockDistraction: Blocked website $host opened in $packageName")
blockedContentGoBack()
return
}

// Block short form content
if (shortsPlatformManager.checkAndBlockShortsOnBrowser(settings, url)) {
return
}
when {
settings.blockedWebsites.contains(host) || nsfwDomains.containsKey(host)
-> {
Log.d(TAG, "blockDistraction: Blocked website $host opened in $packageName")
blockedContentGoBack()
}

// Activate safe search if NSFW is blocked
if (settings.blockNsfwSites) {
applySafeSearch(packageName, url, host)
// Block short form content
shortsPlatformManager.checkAndBlockShortsOnBrowser(settings, url) -> return

// Activate safe search if NSFW is blocked
settings.blockNsfwSites -> applySafeSearch(packageName, url, host)
}
}

Expand All @@ -70,27 +69,25 @@ class BrowserManager(
* @param hostDomain The resolved host name for the provided url.
*/
private fun applySafeSearch(browserPackage: String, url: String, hostDomain: String) {
// For bing, google use &safe=active flag
// For brave, duckduckgo switch domain to safe.[SEARCH_ENGINE_DOMAIN]

// For GOOGLE and BING search engines
if (!url.contains("safe=active") &&
(url.contains("google.com/search?") || url.contains("bing.com/search?"))
) {
val safeUrl = url.replace("/search?", "/search?safe=active&")
redirectUserToUrl(safeUrl, browserPackage)
} else if (
!hostDomain.contains("safe.") &&
(url.contains("search.brave.com/search?") || url.contains("duckduckgo.com/?"))
) {
val safeUrl =
if (hostDomain.contains("search.brave.com")) url.replace(
"search.brave.com",
"safe.search.brave.com"
) else url.replace("duckduckgo.com", "safe.duckduckgo.com")

redirectUserToUrl(safeUrl, browserPackage)
val safeUrl = when {
/// Google search
!url.contains("safe=active")
&& (url.contains("google.com/search?") || url.contains("bing.com/search?"))
-> url.replace("/search?", "/search?safe=active&")

/// Brave search
!hostDomain.contains("safe.") && hostDomain.contains("search.brave.com")
-> url.replace("search.brave.com", "safe.search.brave.com")

/// DuckDuckGo search
!hostDomain.contains("safe.") && hostDomain.contains("duckduckgo.com")
-> url.replace("duckduckgo.com", "safe.duckduckgo.com")

else -> return
}

// Redirect user
redirectUserToUrl(safeUrl, browserPackage)
}

/**
Expand All @@ -107,9 +104,12 @@ class BrowserManager(
// Post to the main thread
ThreadUtils.runOnMainThread {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(Utils.validateHttpsProtocol(url)))
intent.putExtra(Browser.EXTRA_APPLICATION_ID, browserPackage)
intent.setPackage(browserPackage)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.apply {
putExtra(Browser.EXTRA_APPLICATION_ID, browserPackage)
setPackage(browserPackage)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}

if (intent.resolveActivity(context.packageManager) != null) {

/// Toast
Expand Down Expand Up @@ -158,7 +158,8 @@ class BrowserManager(
":id/mozac_browser_toolbar_url_view", // Firefox
":id/url",
":id/search",
":id/url_field",
":id/omnibarTextInput", // Duck duck go
":id/url_field", // Opera
":id/location_bar_edit_text",
":id/addressbarEdit",
":id/bro_omnibar_address_title_text",
Expand Down
Loading

0 comments on commit a5c997f

Please sign in to comment.