Skip to content

Commit fe0380d

Browse files
committed
warpdroid: address Copilot review on blank-URL guards and StrictMode
- StrictMode: guard detectUnbufferedIo() under SDK_INT >= O. The call was unconditional and minSdk is 24, so debug builds on Android 7.x would NoSuchMethodError on Application.onCreate. - DrawerImageLoader.set: cancel any in-flight Glide request on the recycled ImageView before showing the placeholder, so a stale callback from a previous profile can't overwrite it. - loadDrawerAvatar: blank avatar URL now plants the default avatar on the toolbar navigation icon instead of returning silently and leaving whatever icon was there from the previous profile. - EditProfileActivity: blank avatar branch now sets the default avatar drawable on the preview ImageView (the XML has no src fallback, so users without an avatar previously saw an empty preview).
1 parent 3b00f68 commit fe0380d

4 files changed

Lines changed: 45 additions & 22 deletions

File tree

version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.7.16
1+
0.7.17

warpdroid/app/src/main/java/site/warpnet/warpdroid/EditProfileActivity.kt

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -199,17 +199,25 @@ class EditProfileActivity : BaseActivity() {
199199
binding.addFieldButton.isVisible =
200200
(me.source?.fields?.size ?: 0) < maxAccountFields
201201

202-
if (viewModel.avatarData.value == null && me.avatar.isNotBlank()) {
203-
Glide.with(this@EditProfileActivity)
204-
.load(me.avatar)
205-
.placeholder(R.drawable.avatar_default)
206-
.transform(
207-
FitCenter(),
208-
RoundedCorners(
209-
resources.getDimensionPixelSize(R.dimen.avatar_radius_80dp)
202+
if (viewModel.avatarData.value == null) {
203+
if (me.avatar.isNotBlank()) {
204+
Glide.with(this@EditProfileActivity)
205+
.load(me.avatar)
206+
.placeholder(R.drawable.avatar_default)
207+
.transform(
208+
FitCenter(),
209+
RoundedCorners(
210+
resources.getDimensionPixelSize(R.dimen.avatar_radius_80dp)
211+
)
210212
)
211-
)
212-
.into(binding.avatarPreview)
213+
.into(binding.avatarPreview)
214+
} else {
215+
// Profile has no avatar — fall back to
216+
// the same default that Glide would have
217+
// used as a placeholder, otherwise the
218+
// preview shows an empty ImageView.
219+
binding.avatarPreview.setImageResource(R.drawable.avatar_default)
220+
}
213221
}
214222

215223
if (viewModel.headerData.value == null && me.header.isNotBlank()) {

warpdroid/app/src/main/java/site/warpnet/warpdroid/MainActivity.kt

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import androidx.viewpager2.widget.MarginPageTransformer
6363
import com.bumptech.glide.Glide
6464
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
6565
import com.bumptech.glide.request.target.CustomTarget
66+
import androidx.core.content.ContextCompat
6667
import com.bumptech.glide.request.target.FixedSizeDrawable
6768
import com.bumptech.glide.request.transition.Transition
6869
import com.google.android.material.R as materialR
@@ -580,8 +581,11 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
580581
// Warpnet has no HTTP URLs for headers/avatars in some
581582
// states (newly-paired profile, etc.); skip the Glide
582583
// request entirely so logcat isn't spammed with
583-
// "Load failed for []" for an empty Uri.
584+
// "Load failed for []" for an empty Uri. Cancel any
585+
// in-flight request on this recycled ImageView first so
586+
// a stale callback can't overwrite the placeholder.
584587
if (uri.toString().isBlank()) {
588+
Glide.with(imageView).clear(imageView)
585589
imageView.setImageDrawable(placeholder)
586590
return
587591
}
@@ -860,7 +864,6 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
860864

861865
@SuppressLint("CheckResult")
862866
private fun loadDrawerAvatar(avatarUrl: String, showPlaceholder: Boolean = true) {
863-
if (avatarUrl.isBlank()) return
864867
val hideTopToolbar = preferences.getBoolean(PrefKeys.HIDE_TOP_TOOLBAR, false)
865868
val animateAvatars = preferences.getBoolean(PrefKeys.ANIMATE_GIF_AVATARS, false)
866869

@@ -877,6 +880,16 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
877880

878881
val navIconSize = resources.getDimensionPixelSize(R.dimen.avatar_toolbar_nav_icon_size)
879882

883+
if (avatarUrl.isBlank()) {
884+
// No URL to load — set the default avatar on the toolbar
885+
// instead of letting Glide log "Load failed for []" or
886+
// leaving the nav icon stale from a previous profile.
887+
ContextCompat.getDrawable(this, R.drawable.avatar_default)?.let {
888+
activeToolbar.navigationIcon = FixedSizeDrawable(it, navIconSize, navIconSize)
889+
}
890+
return
891+
}
892+
880893
if (animateAvatars) {
881894
Glide.with(this)
882895
.asDrawable()

warpdroid/app/src/main/java/site/warpnet/warpdroid/WarpdroidApplication.kt

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,17 @@ class WarpdroidApplication :
9191
// StrictMode off — penalties are intentionally log-only so a
9292
// missed read doesn't crash a user.
9393
if (BuildConfig.DEBUG) {
94-
StrictMode.setThreadPolicy(
95-
StrictMode.ThreadPolicy.Builder()
96-
.detectDiskReads()
97-
.detectDiskWrites()
98-
.detectNetwork()
99-
.detectUnbufferedIo()
100-
.penaltyLog()
101-
.build()
102-
)
94+
val threadPolicy = StrictMode.ThreadPolicy.Builder()
95+
.detectDiskReads()
96+
.detectDiskWrites()
97+
.detectNetwork()
98+
.penaltyLog()
99+
// detectUnbufferedIo requires API 26 (O); minSdk is 24 so
100+
// guarding it avoids NoSuchMethodError on Android 7.x.
101+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
102+
threadPolicy.detectUnbufferedIo()
103+
}
104+
StrictMode.setThreadPolicy(threadPolicy.build())
103105
StrictMode.setVmPolicy(
104106
StrictMode.VmPolicy.Builder()
105107
.detectLeakedClosableObjects()

0 commit comments

Comments
 (0)