Skip to content

Commit 8fd1b54

Browse files
Merge pull request #2822 from hussainmohd-a/dev-v055y
v055y
2 parents 0aa0b54 + b9fb46d commit 8fd1b54

121 files changed

Lines changed: 5214 additions & 2647 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/build.gradle

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ def isFdroidBuildServer = fdroidBuildServer != null && !fdroidBuildServer.isEmpt
1919
def deGoogled = !apkBuild || fdroidBuild || isFdroidBuildServer
2020
def shouldSplit = !alphaBuild
2121

22+
// Pass -PwebsiteDegoogled=true when building the fdroid flavor with our own keys.
23+
// Official F-Droid builds omit this flag and will be labeled as "fdroid".
24+
def isWebsiteDegoogled = project.hasProperty("websiteDegoogled") &&
25+
project.property("websiteDegoogled").toString().toBoolean()
26+
2227
println("app-task names: '$taskNames'")
2328
println("gradle deGoogled? $deGoogled (fdroidBuild: $fdroidBuild, fdroidBuildServer: $isFdroidBuildServer, apkBuild: $apkBuild)")
2429
println("gradle alphaBuild? $alphaBuild, should split? $shouldSplit")
@@ -61,6 +66,8 @@ def getVersionCode = {
6166
return code
6267
}
6368

69+
def appVersionCode = getVersionCode()
70+
6471
try {
6572
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
6673
} catch (Exception ex) {
@@ -88,6 +95,8 @@ android {
8895
minSdkVersion(23)
8996
targetSdkVersion 35
9097
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
98+
// Defaults to false; the fdroid flavor overrides it via -PwebsiteDegoogled=true.
99+
buildConfigField "boolean", "IS_WEBSITE_DEGOOGLD_BUILD", "false"
91100
}
92101

93102
signingConfigs {
@@ -266,6 +275,8 @@ android {
266275
}
267276
fdroid {
268277
dimension "releaseChannel"
278+
// true only when built with -PwebsiteDegoogled=true (our own keys).
279+
buildConfigField "boolean", "IS_WEBSITE_DEGOOGLD_BUILD", String.valueOf(isWebsiteDegoogled)
269280
}
270281
website {
271282
dimension "releaseChannel"
@@ -277,6 +288,9 @@ android {
277288
// for build type alpha, versionCode is set in env overriding gradle.properties
278289
versionCode = getVersionCode()
279290
versionName = gitVersion
291+
// add base version code to the build config, so that if there is override of
292+
// version numbers by some builds (because of split apks)
293+
buildConfigField "int", "BASE_VERSION_CODE", String.valueOf(appVersionCode)
280294
vectorDrawables.useSupportLibrary = true
281295
}
282296
}
@@ -383,9 +397,7 @@ dependencies {
383397

384398
// add ":debug" suffix to the dependency to include debug symbols
385399
download firestackDependency()
386-
websiteImplementation firestackDependency()
387-
fdroidImplementation firestackDependency()
388-
playImplementation firestackDependency()
400+
implementation firestackDependency()
389401

390402
// Work manager
391403
implementation('androidx.work:work-runtime-ktx:2.11.2') {

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

Lines changed: 149 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,32 @@
1616
package com.celzero.bravedns.adapter
1717

1818
import Logger
19+
import Logger.LOG_TAG_DNS
1920
import Logger.LOG_TAG_UI
2021
import android.content.Context
22+
import android.graphics.drawable.Drawable
2123
import android.os.Bundle
2224
import android.view.LayoutInflater
2325
import android.view.View
2426
import android.view.ViewGroup
27+
import android.widget.ImageView
2528
import android.widget.Toast
2629
import androidx.appcompat.app.AppCompatActivity
2730
import androidx.lifecycle.LifecycleOwner
2831
import androidx.paging.PagingDataAdapter
2932
import androidx.recyclerview.widget.DiffUtil
3033
import androidx.recyclerview.widget.RecyclerView
34+
import com.bumptech.glide.Glide
35+
import com.bumptech.glide.RequestBuilder
36+
import com.bumptech.glide.load.engine.DiskCacheStrategy
37+
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
38+
import com.bumptech.glide.request.target.CustomViewTarget
39+
import com.bumptech.glide.request.transition.DrawableCrossFadeFactory
40+
import com.bumptech.glide.request.transition.Transition
3141
import com.celzero.bravedns.R
3242
import com.celzero.bravedns.data.AppConnection
3343
import com.celzero.bravedns.databinding.ListItemAppDomainDetailsBinding
44+
import com.celzero.bravedns.glide.FavIconDownloader
3445
import com.celzero.bravedns.service.DomainRulesManager
3546
import com.celzero.bravedns.service.VpnController
3647
import com.celzero.bravedns.ui.bottomsheet.AppDomainRulesBottomSheet
@@ -137,14 +148,16 @@ class AppWiseDomainsAdapter(
137148
} else {
138149
b.acdIpAddress.text = conn.appOrDnsName
139150
}
140-
b.acdFlag.visibility = View.VISIBLE
141-
b.acdFlag.text = conn.flag
151+
//b.acdFlag.visibility = View.VISIBLE
152+
//b.acdFlag.text = conn.flag
153+
showFlagOrIcon(conn.appOrDnsName, conn.flag)
142154
return
143155
}
144156

145157
b.acdCount.text = conn.count.toString()
146158
b.acdDomain.text = conn.appOrDnsName
147-
b.acdFlag.text = conn.flag
159+
//b.acdFlag.text = conn.flag
160+
showFlagOrIcon(conn.appOrDnsName, conn.flag)
148161
if (conn.ipAddress.isNotEmpty()) {
149162
b.acdIpAddress.visibility = View.VISIBLE
150163
b.acdIpAddress.text = beautifyIpString(conn.ipAddress)
@@ -154,6 +167,139 @@ class AppWiseDomainsAdapter(
154167
updateStatusUi(conn)
155168
}
156169

170+
private fun showFlagOrIcon(query: String?, flag: String? = null) {
171+
b.acdFlag.text = flag
172+
if (query == null) {
173+
hideFavIcon()
174+
showFlag()
175+
return
176+
}
177+
val query = query.dropLastWhile { it == ',' }
178+
179+
// no need to check in glide cache if the value is available in failed
180+
// cache
181+
if (FavIconDownloader.isUrlAvailableInFailedCache(query) != null) {
182+
hideFavIcon()
183+
showFlag()
184+
} else {
185+
// Glide will cache the icons against the urls. To extract the fav
186+
// icon from the cache, first verify that the cache is available with
187+
// the next dns url. If it is not available then glide will throw an
188+
// error, do the duckduckgo url check in that case.
189+
displayNextDnsFavIcon(query)
190+
}
191+
}
192+
193+
private fun displayNextDnsFavIcon(query: String) {
194+
// url to check if the icon is cached from nextdns
195+
val nextDnsUrl = FavIconDownloader.constructFavIcoUrlNextDns(query)
196+
// url to check if the icon is cached from duckduckgo
197+
val duckDuckGoUrl = FavIconDownloader.constructFavUrlDuckDuckGo(query)
198+
// subdomain to check if the icon is cached from duckduckgo
199+
val duckduckgoDomainURL = FavIconDownloader.getDomainUrlFromFdqnDuckduckgo(query)
200+
try {
201+
val factory = DrawableCrossFadeFactory.Builder().setCrossFadeEnabled(true).build()
202+
var request = Glide.with(context.applicationContext)
203+
.load(nextDnsUrl)
204+
.onlyRetrieveFromCache(true)
205+
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
206+
.transition(DrawableTransitionOptions.withCrossFade(factory))
207+
208+
val errorRequest = displayDuckduckgoFavIcon(duckDuckGoUrl, duckduckgoDomainURL)
209+
if (errorRequest != null) {
210+
request = request.error(errorRequest)
211+
}
212+
213+
request.into(
214+
object : CustomViewTarget<ImageView, Drawable>(b.acdIcon) {
215+
override fun onLoadFailed(errorDrawable: Drawable?) {
216+
showFlag()
217+
hideFavIcon()
218+
}
219+
220+
override fun onResourceReady(
221+
resource: Drawable,
222+
transition: Transition<in Drawable>?
223+
) {
224+
hideFlag()
225+
showFavIcon(resource)
226+
}
227+
228+
override fun onResourceCleared(placeholder: Drawable?) {
229+
hideFavIcon()
230+
showFlag()
231+
}
232+
}
233+
)
234+
} catch (_: Exception) {
235+
Logger.d(LOG_TAG_DNS, "err loading icon, load flag instead")
236+
displayDuckduckgoFavIcon(duckDuckGoUrl, duckduckgoDomainURL)?.into(
237+
object : CustomViewTarget<ImageView, Drawable>(b.acdIcon) {
238+
override fun onLoadFailed(errorDrawable: Drawable?) {
239+
showFlag()
240+
hideFavIcon()
241+
}
242+
243+
override fun onResourceReady(
244+
resource: Drawable,
245+
transition: Transition<in Drawable>?
246+
) {
247+
hideFlag()
248+
showFavIcon(resource)
249+
}
250+
251+
override fun onResourceCleared(placeholder: Drawable?) {
252+
hideFavIcon()
253+
showFlag()
254+
}
255+
}
256+
)
257+
}
258+
}
259+
260+
/**
261+
* Loads the fav icons from the cache, the icons are cached by favIconDownloader. On
262+
* failure, will check if there is a icon for top level domain is available in cache. Else,
263+
* will show the Flag.
264+
*
265+
* This method will be executed only when show fav icon setting is turned on.
266+
*/
267+
private fun displayDuckduckgoFavIcon(url: String, subDomainURL: String): RequestBuilder<Drawable>? {
268+
return try {
269+
val factory = DrawableCrossFadeFactory.Builder().setCrossFadeEnabled(true).build()
270+
Glide.with(context.applicationContext)
271+
.load(url)
272+
.onlyRetrieveFromCache(true)
273+
.diskCacheStrategy(DiskCacheStrategy.AUTOMATIC)
274+
.error(
275+
Glide.with(context.applicationContext)
276+
.load(subDomainURL)
277+
.onlyRetrieveFromCache(true)
278+
)
279+
.transition(DrawableTransitionOptions.withCrossFade(factory))
280+
} catch (e: Exception) {
281+
null
282+
}
283+
}
284+
285+
private fun showFavIcon(drawable: Drawable) {
286+
b.acdIcon.visibility = View.VISIBLE
287+
b.acdIcon.setImageDrawable(drawable)
288+
}
289+
290+
private fun hideFavIcon() {
291+
b.acdIcon.visibility = View.GONE
292+
b.acdIcon.setImageDrawable(null)
293+
}
294+
295+
private fun showFlag() {
296+
b.acdFlag.visibility = View.VISIBLE
297+
}
298+
299+
private fun hideFlag() {
300+
b.acdFlag.visibility = View.GONE
301+
}
302+
157303
private fun setupClickListeners(conn: AppConnection) {
158304
b.acdContainer.setOnClickListener {
159305
if (isActiveConn) {

0 commit comments

Comments
 (0)