Skip to content

Commit 3c67ba6

Browse files
Merge pull request #2480 from hussainmohd-a/main
v055v additional changes
2 parents f365083 + ba5b898 commit 3c67ba6

File tree

21 files changed

+227
-251
lines changed

21 files changed

+227
-251
lines changed

app/src/main/java/com/celzero/bravedns/adapter/BubbleAllowedAppsAdapter.kt renamed to app/src/full/java/com/celzero/bravedns/adapter/BubbleAllowedAppsAdapter.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.celzero.bravedns.adapter
1717

18+
import android.R
1819
import android.view.LayoutInflater
1920
import android.view.ViewGroup
2021
import androidx.paging.PagingDataAdapter
@@ -43,6 +44,10 @@ class BubbleAllowedAppsAdapter(
4344
RecyclerView.ViewHolder(binding.root) {
4445

4546
fun bind(app: AllowedAppInfo) {
47+
// Enable marquee reliably.
48+
binding.allowedAppName.isSelected = true
49+
50+
// appName is already decorated ("App + N other apps") by paging source.
4651
binding.allowedAppName.text = app.appName
4752

4853
// Calculate time remaining
@@ -62,7 +67,7 @@ class BubbleAllowedAppsAdapter(
6267
val icon = packageManager.getApplicationIcon(app.packageName)
6368
binding.allowedAppIcon.setImageDrawable(icon)
6469
} catch (_: Exception) {
65-
binding.allowedAppIcon.setImageResource(android.R.drawable.sym_def_app_icon)
70+
binding.allowedAppIcon.setImageResource(R.drawable.sym_def_app_icon)
6671
}
6772

6873
binding.allowedRemoveBtn.setOnClickListener {
@@ -87,4 +92,3 @@ class BubbleAllowedAppsAdapter(
8792
}
8893
}
8994
}
90-

app/src/full/java/com/celzero/bravedns/adapter/BubbleBlockedAppsAdapter.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ class BubbleBlockedAppsAdapter(
7171
) : RecyclerView.ViewHolder(binding.root) {
7272

7373
fun bind(app: BlockedAppInfo) {
74+
// Enable marquee reliably (focus is usually held by other views like buttons).
75+
binding.blockedAppName.isSelected = true
76+
7477
binding.blockedAppName.text = app.appName
7578
binding.blockedAppPackage.text = app.packageName
7679
binding.blockedAppCount.text = itemView.context.getString(
@@ -125,4 +128,3 @@ class BubbleBlockedAppsAdapter(
125128
}
126129
}
127130
}
128-

app/src/main/java/com/celzero/bravedns/adapter/EventsAdapter.kt renamed to app/src/full/java/com/celzero/bravedns/adapter/EventsAdapter.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import android.view.View
2424
import android.view.ViewGroup
2525
import android.view.animation.AccelerateDecelerateInterpolator
2626
import android.widget.Toast
27+
import androidx.paging.PagingDataAdapter
2728
import androidx.recyclerview.widget.DiffUtil
2829
import androidx.recyclerview.widget.RecyclerView
2930
import com.celzero.bravedns.R
@@ -35,7 +36,7 @@ import java.util.Date
3536
import java.util.Locale
3637

3738
class EventsAdapter(private val context: Context) :
38-
androidx.paging.PagingDataAdapter<Event, EventsAdapter.EventViewHolder>(EventDiffCallback()) {
39+
PagingDataAdapter<Event, EventsAdapter.EventViewHolder>(EventDiffCallback()) {
3940

4041
companion object {
4142
private const val ANIMATION_DURATION = 300L

app/src/full/java/com/celzero/bravedns/service/WireguardManager.kt

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -781,14 +781,6 @@ object WireguardManager : KoinComponent {
781781
disableConfig(cf)
782782
}
783783

784-
if (config == null) {
785-
Logger.e(LOG_TAG_PROXY, "deleteConfig: wg not found, id: $id, ${configs.size}")
786-
io {
787-
db.deleteConfig(id)
788-
mappings.remove(mappings.find { it.id == id })
789-
}
790-
return
791-
}
792784
io {
793785
val fileName = getConfigFileName(id)
794786
val file = File(getConfigFilePath(), fileName)
@@ -800,7 +792,7 @@ object WireguardManager : KoinComponent {
800792
val proxyId = ID_WG_BASE + id
801793
ProxyManager.removeProxyId(proxyId)
802794
mappings.remove(mappings.find { it.id == id })
803-
configs.remove(config)
795+
if (config != null) configs.remove(config)
804796
WgHopManager.handleWgDelete(id)
805797
}
806798
}

app/src/full/java/com/celzero/bravedns/ui/activity/BubbleActivity.kt

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import com.celzero.bravedns.data.BlockedAppInfo
3636
import com.celzero.bravedns.viewmodel.BlockedAppsBubbleViewModel
3737
import com.celzero.bravedns.database.AppInfoRepository
3838
import com.celzero.bravedns.database.ConnectionTrackerDAO
39+
import com.celzero.bravedns.database.DnsLogDAO
3940
import com.celzero.bravedns.databinding.ActivityBubbleBinding
4041
import com.celzero.bravedns.service.FirewallManager
4142
import com.celzero.bravedns.service.PersistentState
@@ -71,13 +72,16 @@ class BubbleActivity : AppCompatActivity(R.layout.activity_bubble) {
7172
private val persistentState by inject<PersistentState>()
7273
private val connectionTrackerDAO by inject<ConnectionTrackerDAO>()
7374
private val appInfoRepository by inject<AppInfoRepository>()
75+
private val dnsLogDAO by inject<DnsLogDAO>()
7476

7577
private lateinit var blockedAdapter: BubbleBlockedAppsAdapter
7678
private lateinit var allowedAdapter: BubbleAllowedAppsAdapter
7779

7880
private var blockedCollectJob: kotlinx.coroutines.Job? = null
7981
private var allowedCollectJob: kotlinx.coroutines.Job? = null
8082

83+
private var recyclerDecorationsAdded: Boolean = false
84+
8185
companion object {
8286
private const val TAG = "BubbleActivity"
8387
private const val PAGE_SIZE = 20
@@ -156,7 +160,7 @@ class BubbleActivity : AppCompatActivity(R.layout.activity_bubble) {
156160
enablePlaceholders = false
157161
),
158162
pagingSourceFactory = {
159-
AllowedAppsBubbleViewModel(appInfoRepository, now, this@BubbleActivity)
163+
AllowedAppsBubbleViewModel(appInfoRepository, now)
160164
}
161165
).flow.cachedIn(lifecycleScope)
162166

@@ -196,8 +200,8 @@ class BubbleActivity : AppCompatActivity(R.layout.activity_bubble) {
196200
pagingSourceFactory = {
197201
BlockedAppsBubbleViewModel(
198202
connectionTrackerDAO,
203+
dnsLogDAO,
199204
appInfoRepository,
200-
this@BubbleActivity,
201205
last15Mins,
202206
tempAllowedUids
203207
)
@@ -224,14 +228,6 @@ class BubbleActivity : AppCompatActivity(R.layout.activity_bubble) {
224228
}
225229
}
226230

227-
private fun loadAllowedApps() {
228-
startAllowedCollector()
229-
}
230-
231-
private fun loadBlockedApps() {
232-
startBlockedCollector()
233-
}
234-
235231
private fun allowApp(blockedApp: BlockedAppInfo) {
236232
// Optimistic UI update: remove right away from blocked list for fast feedback.
237233
// PagingDataAdapter doesn't support direct removal; we force a refresh after DB update,
@@ -288,17 +284,19 @@ class BubbleActivity : AppCompatActivity(R.layout.activity_bubble) {
288284
b.bubbleRecyclerView.apply {
289285
layoutManager = LinearLayoutManager(this@BubbleActivity)
290286
adapter = blockedAdapter
291-
// Add item spacing for premium look
292-
addItemDecoration(object : androidx.recyclerview.widget.RecyclerView.ItemDecoration() {
293-
override fun getItemOffsets(
294-
outRect: android.graphics.Rect,
295-
view: View,
296-
parent: androidx.recyclerview.widget.RecyclerView,
297-
state: androidx.recyclerview.widget.RecyclerView.State
298-
) {
299-
outRect.bottom = 16 // 16dp spacing
300-
}
301-
})
287+
if (!recyclerDecorationsAdded) {
288+
// Smaller spacing; item XML already has margins.
289+
addItemDecoration(object : androidx.recyclerview.widget.RecyclerView.ItemDecoration() {
290+
override fun getItemOffsets(
291+
outRect: android.graphics.Rect,
292+
view: View,
293+
parent: androidx.recyclerview.widget.RecyclerView,
294+
state: androidx.recyclerview.widget.RecyclerView.State
295+
) {
296+
outRect.bottom = 4 // 4dp
297+
}
298+
})
299+
}
302300
}
303301

304302
// Setup allowed apps RecyclerView
@@ -308,16 +306,19 @@ class BubbleActivity : AppCompatActivity(R.layout.activity_bubble) {
308306
b.bubbleAllowedRecyclerView.apply {
309307
layoutManager = LinearLayoutManager(this@BubbleActivity)
310308
adapter = allowedAdapter
311-
addItemDecoration(object : androidx.recyclerview.widget.RecyclerView.ItemDecoration() {
312-
override fun getItemOffsets(
313-
outRect: android.graphics.Rect,
314-
view: View,
315-
parent: androidx.recyclerview.widget.RecyclerView,
316-
state: androidx.recyclerview.widget.RecyclerView.State
317-
) {
318-
outRect.bottom = 16 // 16dp spacing
319-
}
320-
})
309+
if (!recyclerDecorationsAdded) {
310+
addItemDecoration(object : androidx.recyclerview.widget.RecyclerView.ItemDecoration() {
311+
override fun getItemOffsets(
312+
outRect: android.graphics.Rect,
313+
view: View,
314+
parent: androidx.recyclerview.widget.RecyclerView,
315+
state: androidx.recyclerview.widget.RecyclerView.State
316+
) {
317+
outRect.bottom = 4 // 4dp
318+
}
319+
})
320+
recyclerDecorationsAdded = true
321+
}
321322
}
322323
}
323324

@@ -390,7 +391,7 @@ class BubbleActivity : AppCompatActivity(R.layout.activity_bubble) {
390391
b.bubbleAllowedAppsLl.visibility = View.GONE
391392
b.bubbleRecyclerView.visibility = View.GONE
392393
b.bubbleEmptyState.visibility = View.VISIBLE
393-
b.bubbleEmptyTitle.text = "VPN is off" // keep inline for now
394+
b.bubbleEmptyTitle.setText(R.string.bubble_empty_state_title)
394395
}
395396
}
396397

app/src/full/java/com/celzero/bravedns/viewmodel/AllowedAppsBubbleViewModel.kt

Lines changed: 27 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,57 +28,51 @@ import com.celzero.bravedns.database.AppInfoRepository
2828
*/
2929
class AllowedAppsBubbleViewModel(
3030
private val appInfoRepository: AppInfoRepository,
31-
private val now: Long,
32-
private val context: android.content.Context
31+
private val now: Long
3332
) : PagingSource<Int, AllowedAppInfo>() {
3433

3534
companion object {
3635
private const val TAG = "AllowedAppsPagingSource"
36+
private const val TEMP_ALLOW_MS = 15 * 60 * 1000L
3737
}
3838

3939
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, AllowedAppInfo> {
4040
return try {
41-
// Get temp allowed apps from database
41+
// DB returns one row per package; collapse to one row per UID.
4242
val tempAllowedApps = appInfoRepository.getAllTempAllowedApps(now)
4343

44-
// Convert to AllowedAppInfo
45-
val allowedApps = tempAllowedApps.mapNotNull { appInfo ->
46-
try {
47-
val displayName = decorateNameIfSharedUid(appInfo.appName, appInfo.uid)
48-
AllowedAppInfo(
49-
packageName = appInfo.packageName,
50-
appName = displayName,
51-
uid = appInfo.uid,
52-
allowedAt = appInfo.tempAllowExpiryTime - (15 * 60 * 1000) // Calculate when it was allowed
53-
)
54-
} catch (e: Exception) {
55-
Logger.e(TAG, "Error mapping app info: ${e.message}", e)
56-
null
57-
}
58-
}
44+
val byUid = tempAllowedApps.groupBy { it.uid }
45+
46+
val allowedApps = byUid.values.mapNotNull { appsForUid ->
47+
val primary = appsForUid.firstOrNull() ?: return@mapNotNull null
48+
49+
// If multiple packages share this UID, show "App + N other apps".
50+
val otherCount = (appsForUid.size - 1).coerceAtLeast(0)
51+
val displayName =
52+
if (otherCount > 0) "${primary.appName} + $otherCount other apps" else primary.appName
53+
54+
// tempAllowExpiryTime is stored per row; for UID aggregation, take the max.
55+
val expiry = appsForUid.maxOfOrNull { it.tempAllowExpiryTime } ?: primary.tempAllowExpiryTime
56+
57+
AllowedAppInfo(
58+
packageName = primary.packageName,
59+
appName = displayName,
60+
uid = primary.uid,
61+
allowedAt = expiry - TEMP_ALLOW_MS,
62+
otherAppsCount = otherCount
63+
)
64+
}.sortedByDescending { it.allowedAt }
5965

6066
LoadResult.Page(
6167
data = allowedApps,
62-
prevKey = null, // Only one page for now
63-
nextKey = null // Only one page for now
68+
prevKey = null,
69+
nextKey = null
6470
)
6571
} catch (e: Exception) {
6672
Logger.e(TAG, "Error loading allowed apps: ${e.message}", e)
6773
LoadResult.Error(e)
6874
}
6975
}
7076

71-
override fun getRefreshKey(state: PagingState<Int, AllowedAppInfo>): Int? {
72-
return null
73-
}
74-
75-
private fun decorateNameIfSharedUid(appName: String, uid: Int): String {
76-
return try {
77-
val pkgs = context.packageManager.getPackagesForUid(uid)
78-
val otherCount = (pkgs?.size ?: 0) - 1
79-
if (otherCount > 0) "$appName + $otherCount other apps" else appName
80-
} catch (_: Exception) {
81-
appName
82-
}
83-
}
77+
override fun getRefreshKey(state: PagingState<Int, AllowedAppInfo>): Int? = null
8478
}

0 commit comments

Comments
 (0)