@@ -25,7 +25,10 @@ import android.view.LayoutInflater
2525import android.view.View
2626import android.view.ViewGroup
2727import androidx.core.content.ContextCompat
28+ import androidx.core.view.ViewCompat.isAttachedToWindow
29+ import androidx.fragment.app.Fragment
2830import androidx.fragment.app.FragmentActivity
31+ import androidx.lifecycle.Lifecycle
2932import androidx.lifecycle.LifecycleOwner
3033import androidx.lifecycle.lifecycleScope
3134import androidx.paging.PagingDataAdapter
@@ -262,136 +265,143 @@ class ConnectionTrackerAdapter(private val context: Context) :
262265 }
263266
264267 private fun displaySummaryDetails (ct : ConnectionTracker ) {
265- val connType = ConnectionTracker .ConnType .get(ct.connType)
266- b.connectionDataUsage.text = " "
267- b.connectionDelay.text = " "
268- if (
269- ct.duration == 0 &&
270- ct.downloadBytes == 0L &&
271- ct.uploadBytes == 0L &&
272- ct.message.isEmpty()
273- ) {
274- var hasMinSummary = false
275- if (VpnController .hasCid(ct.connId, ct.uid)) {
276- b.connectionSummaryLl.visibility = View .VISIBLE
277- b.connectionDataUsage.text = context.getString(R .string.lbl_active)
278- b.connectionDuration.text = context.getString(R .string.symbol_green_circle)
279- b.connectionDelay.text = " "
280- hasMinSummary = true
281- } else {
268+ io {
269+ val hasCid = VpnController .hasCid(ct.connId, ct.uid)
270+ val connType = ConnectionTracker .ConnType .get(ct.connType)
271+ uiCtx {
282272 b.connectionDataUsage.text = " "
283- b.connectionDuration.text = " "
284- }
285- if (connType.isMetered()) {
286- b.connectionDelay.text = context.getString(R .string.symbol_currency)
287- hasMinSummary = true
288- } else {
289273 b.connectionDelay.text = " "
290- }
274+ if (
275+ ct.duration == 0 &&
276+ ct.downloadBytes == 0L &&
277+ ct.uploadBytes == 0L &&
278+ ct.message.isEmpty()
279+ ) {
280+ var hasMinSummary = false
281+ if (hasCid) {
282+ b.connectionSummaryLl.visibility = View .VISIBLE
283+ b.connectionDataUsage.text = context.getString(R .string.lbl_active)
284+ b.connectionDuration.text = context.getString(R .string.symbol_green_circle)
285+ b.connectionDelay.text = " "
286+ hasMinSummary = true
287+ } else {
288+ b.connectionDataUsage.text = " "
289+ b.connectionDuration.text = " "
290+ }
291+ if (connType.isMetered()) {
292+ b.connectionDelay.text = context.getString(R .string.symbol_currency)
293+ hasMinSummary = true
294+ } else {
295+ b.connectionDelay.text = " "
296+ }
297+
298+ if (isRpnProxy(ct.rpid)) {
299+ b.connectionSummaryLl.visibility = View .VISIBLE
300+ b.connectionDelay.text =
301+ context.getString(
302+ R .string.ci_desc,
303+ b.connectionDelay.text,
304+ context.getString(R .string.symbol_sparkle)
305+ )
306+ } else if (isConnectionProxied(ct.blockedByRule, ct.proxyDetails)) {
307+ b.connectionSummaryLl.visibility = View .VISIBLE
308+ b.connectionDelay.text =
309+ context.getString(
310+ R .string.ci_desc,
311+ b.connectionDelay.text,
312+ context.getString(R .string.symbol_key)
313+ )
314+ hasMinSummary = true
315+ }
316+ if (! hasMinSummary) {
317+ b.connectionSummaryLl.visibility = View .GONE
318+ }
319+ return @uiCtx
320+ }
291321
292- if (isRpnProxy(ct.rpid)) {
293322 b.connectionSummaryLl.visibility = View .VISIBLE
294- b.connectionDelay.text =
323+ val duration = getDurationInHumanReadableFormat(context, ct.duration)
324+ b.connectionDuration.text = context.getString(R .string.single_argument, duration)
325+ // add unicode for download and upload
326+ val download =
295327 context.getString(
296- R .string.ci_desc,
297- b.connectionDelay.text,
298- context.getString(R .string.symbol_sparkle)
328+ R .string.symbol_download,
329+ Utilities .humanReadableByteCount(ct.downloadBytes, true )
299330 )
300- } else if (isConnectionProxied(ct.blockedByRule, ct.proxyDetails)) {
301- b.connectionSummaryLl.visibility = View .VISIBLE
302- b.connectionDelay.text =
331+ val upload =
303332 context.getString(
304- R .string.ci_desc,
305- b.connectionDelay.text,
306- context.getString(R .string.symbol_key)
333+ R .string.symbol_upload,
334+ Utilities .humanReadableByteCount(ct.uploadBytes, true )
307335 )
308- hasMinSummary = true
309- }
310- if (! hasMinSummary) {
311- b.connectionSummaryLl.visibility = View .GONE
312- }
313- return
314- }
336+ b.connectionDataUsage.text = context.getString(R .string.two_argument, upload, download)
337+ b.connectionDelay.text = " "
338+ if (connType.isMetered()) {
339+ b.connectionDelay.text =
340+ context.getString(
341+ R .string.ci_desc,
342+ b.connectionDelay.text,
343+ context.getString(R .string.symbol_currency)
344+ )
345+ }
346+ if (isConnectionHeavier(ct)) {
347+ b.connectionDelay.text =
348+ context.getString(
349+ R .string.ci_desc,
350+ b.connectionDelay.text,
351+ context.getString(R .string.symbol_heavy)
352+ )
353+ }
354+ if (isConnectionSlower(ct)) {
355+ b.connectionDelay.text =
356+ context.getString(
357+ R .string.ci_desc,
358+ b.connectionDelay.text,
359+ context.getString(R .string.symbol_turtle)
360+ )
361+ }
362+ // bunny in case rpid as present, key in case of proxy
363+ // bunny and key indicate conn is proxied, so its enough to show one of them
364+ if (isRpnProxy(ct.rpid)) {
365+ b.connectionSummaryLl.visibility = View .VISIBLE
366+ b.connectionDelay.text =
367+ context.getString(
368+ R .string.ci_desc,
369+ b.connectionDelay.text,
370+ context.getString(R .string.symbol_sparkle)
371+ )
372+ } else if (containsRelayProxy(ct.rpid)) {
373+ b.connectionDelay.text =
374+ context.getString(
375+ R .string.ci_desc,
376+ b.connectionDelay.text,
377+ context.getString(R .string.symbol_bunny)
378+ )
379+ } else if (isConnectionProxied(ct.blockedByRule, ct.proxyDetails)) {
380+ b.connectionDelay.text =
381+ context.getString(
382+ R .string.ci_desc,
383+ b.connectionDelay.text,
384+ context.getString(R .string.symbol_key)
385+ )
386+ }
315387
316- b.connectionSummaryLl.visibility = View .VISIBLE
317- val duration = getDurationInHumanReadableFormat(context, ct.duration)
318- b.connectionDuration.text = context.getString(R .string.single_argument, duration)
319- // add unicode for download and upload
320- val download =
321- context.getString(
322- R .string.symbol_download,
323- Utilities .humanReadableByteCount(ct.downloadBytes, true )
324- )
325- val upload =
326- context.getString(
327- R .string.symbol_upload,
328- Utilities .humanReadableByteCount(ct.uploadBytes, true )
329- )
330- b.connectionDataUsage.text = context.getString(R .string.two_argument, upload, download)
331- b.connectionDelay.text = " "
332- if (connType.isMetered()) {
333- b.connectionDelay.text =
334- context.getString(
335- R .string.ci_desc,
336- b.connectionDelay.text,
337- context.getString(R .string.symbol_currency)
338- )
339- }
340- if (isConnectionHeavier(ct)) {
341- b.connectionDelay.text =
342- context.getString(
343- R .string.ci_desc,
344- b.connectionDelay.text,
345- context.getString(R .string.symbol_heavy)
346- )
347- }
348- if (isConnectionSlower(ct)) {
349- b.connectionDelay.text =
350- context.getString(
351- R .string.ci_desc,
352- b.connectionDelay.text,
353- context.getString(R .string.symbol_turtle)
354- )
355- }
356- // bunny in case rpid as present, key in case of proxy
357- // bunny and key indicate conn is proxied, so its enough to show one of them
358- if (isRpnProxy(ct.rpid)) {
359- b.connectionSummaryLl.visibility = View .VISIBLE
360- b.connectionDelay.text =
361- context.getString(
362- R .string.ci_desc,
363- b.connectionDelay.text,
364- context.getString(R .string.symbol_sparkle)
365- )
366- } else if (containsRelayProxy(ct.rpid)) {
367- b.connectionDelay.text =
368- context.getString(
369- R .string.ci_desc,
370- b.connectionDelay.text,
371- context.getString(R .string.symbol_bunny)
372- )
373- } else if (isConnectionProxied(ct.blockedByRule, ct.proxyDetails)) {
374- b.connectionDelay.text =
375- context.getString(
376- R .string.ci_desc,
377- b.connectionDelay.text,
378- context.getString(R .string.symbol_key)
379- )
380- }
388+ // rtt -> show rocket if less than 20ms, treat it as rtt
389+ if (isRoundTripShorter(ct.synack, ct.isBlocked)) {
390+ b.connectionDelay.text =
391+ context.getString(
392+ R .string.ci_desc,
393+ b.connectionDelay.text,
394+ context.getString(R .string.symbol_rocket)
395+ )
396+ }
381397
382- // rtt -> show rocket if less than 20ms, treat it as rtt
383- if (isRoundTripShorter(ct.synack, ct.isBlocked)) {
384- b.connectionDelay.text =
385- context.getString(
386- R .string.ci_desc,
387- b.connectionDelay.text,
388- context.getString(R .string.symbol_rocket)
389- )
390- }
398+ if (b.connectionDelay.text.isEmpty() && b.connectionDataUsage.text.isEmpty()) {
399+ b.connectionSummaryLl.visibility = View .GONE
400+ }
391401
392- if (b.connectionDelay.text.isEmpty() && b.connectionDataUsage.text.isEmpty()) {
393- b.connectionSummaryLl.visibility = View .GONE
402+ }
394403 }
404+
395405 }
396406
397407 private fun isRoundTripShorter (rtt : Long , blocked : Boolean ): Boolean {
@@ -433,10 +443,20 @@ class ConnectionTrackerAdapter(private val context: Context) :
433443 }
434444
435445 private fun io (f : suspend () -> Unit ) {
436- (context as LifecycleOwner ).lifecycleScope.launch(Dispatchers .IO ) { f() }
446+ val owner = context as ? LifecycleOwner ? : return
447+
448+ owner.lifecycleScope.launch(Dispatchers .IO ) { f() }
437449 }
438450
439451 private suspend fun uiCtx (f : suspend () -> Unit ) {
440- withContext(Dispatchers .Main ) { f() }
452+ val owner = context as ? LifecycleOwner ? : return
453+
454+ withContext(Dispatchers .Main .immediate) {
455+ if (! owner.lifecycle.currentState.isAtLeast(Lifecycle .State .STARTED )) {
456+ return @withContext
457+ }
458+
459+ f()
460+ }
441461 }
442462}
0 commit comments