Skip to content

Commit 3e22d23

Browse files
authored
Merge pull request #3 from FeernandoOFF/main
Added :: Networking Module & Updated Docs
2 parents 6bc5d17 + ce448c3 commit 3e22d23

10 files changed

Lines changed: 807 additions & 5 deletions

File tree

LOGS_DEMO.gif

6.38 MB
Loading

NETWORK_DEMO.gif

3.52 MB
Loading

README.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,80 @@ Fragment/Activity:
362362

363363
</details>
364364

365+
<details>
366+
<summary>Network Module</summary>
367+
The network module allows you to monitor network requests in the debug menu as well as copying the request body to the
368+
clipboard or multiple requests at once.
369+
370+
**Adding the module**
371+
372+
```kotlin
373+
DebugMenuAttacher.attach(
374+
this,
375+
modules = listOf(
376+
NetworkModule()
377+
// Rest of your modules...
378+
),
379+
)
380+
// or
381+
DebugMenuOverlay(
382+
modules = listOf(
383+
NetworkModule()
384+
// Rest of your modules...
385+
)
386+
)
387+
```
388+
389+
**Intercepting Network Requests**
390+
> Note: This library does not include out-of-the-box integration with OkHttp or any other networking library. Instead,
391+
> you need to intercept the requests yourself and add them to the `DebugNetworkRequests` singleton.
392+
393+
394+
- OKHttp Interceptor (Example):
395+
```kotlin
396+
object DebugMenuInterceptor : Interceptor {
397+
override fun intercept(chain: Interceptor.Chain): Response {
398+
val request = chain.request()
399+
val startTime = System.currentTimeMillis()
400+
val response = chain.proceed(request)
401+
val duration = System.currentTimeMillis() - startTime
402+
var responseBodyString: String? = null
403+
response.body?.let { responseBody ->
404+
val source = responseBody.source()
405+
source.request(Long.MAX_VALUE)
406+
val buffer = source.buffer
407+
responseBodyString = buffer.clone().readString(responseBody.contentType()?.charset() ?: Charsets.UTF_8)
408+
}
409+
410+
val debugRequest = DebugNetworkRequest(
411+
url = request.url.toString(),
412+
method = request.method,
413+
headers = request.headers.toMap(),
414+
responseHeaders = response.headers.toMap(),
415+
body = request.body?.toString() ?: "",
416+
timestamp = startTime,
417+
duration = duration,
418+
isSuccessful = response.isSuccessful,
419+
code = response.code,
420+
error = if (!response.isSuccessful) response.message else null,
421+
response = responseBodyString,
422+
requestSize = request.body?.contentLength() ?: 0
423+
)
424+
425+
DebugNetworkRequests.add(debugRequest)
426+
return response
427+
}
428+
}
429+
430+
// Add the interceptor to your OkHttp client
431+
432+
val okHttpClient = OkHttpClient.Builder()
433+
.addInterceptor(DebugMenuInterceptor)
434+
.build()
435+
```
436+
437+
</details>
438+
365439
### Creating your own Module
366440

367441
You can create custom modules to display any debugging information specific to your app. For example, a network request

app/src/main/java/com/tapado/debugmenuDemo/MainActivity.kt

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ import com.tapadoo.debugmenu.dynamic.DynamicAction
2626
import com.tapadoo.debugmenu.dynamic.DynamicModule
2727
import com.tapadoo.debugmenu.logs.DebugLogs
2828
import com.tapadoo.debugmenu.logs.LoggingModule
29+
import com.tapadoo.debugmenu.network.DebugNetworkEvents
30+
import com.tapadoo.debugmenu.network.DebugNetworkRequest
31+
import com.tapadoo.debugmenu.network.NetworkModule
2932
import timber.log.Timber
33+
import kotlin.random.Random
3034

3135
class MainActivity : ComponentActivity() {
3236
private lateinit var viewModel: DemoViewModel
@@ -84,6 +88,12 @@ class MainActivity : ComponentActivity() {
8488
globalActions = listOf(
8589
DynamicAction("Global Action 1") {
8690
// Perform global action
91+
},
92+
DynamicAction("Add API Call") {
93+
// Mocking API call / Intercept
94+
DebugNetworkEvents.addEvent(
95+
DebugNetworkRequest.random()
96+
)
8797
}
8898
)
8999
),
@@ -94,10 +104,36 @@ class MainActivity : ComponentActivity() {
94104
this@MainActivity.applicationContext.demoDataStore
95105
)
96106
),
107+
NetworkModule()
97108
),
98109
)
99110
}
100111
}
101112
}
102113
}
103-
}
114+
}
115+
116+
private fun DebugNetworkRequest.Companion.random(): DebugNetworkRequest {
117+
val methods = listOf("GET", "POST", "PUT", "DELETE")
118+
val urls = listOf(
119+
"https://api.example.com/users",
120+
"https://api.example.com/products",
121+
"https://api.example.com/orders"
122+
)
123+
val successful = Random.nextBoolean()
124+
125+
return DebugNetworkRequest(
126+
url = urls.random(),
127+
method = methods.random(),
128+
headers = mapOf("Content-Type" to "application/json"),
129+
responseHeaders = mapOf("Content-Type" to "application/json"),
130+
body = """{"id": ${Random.nextInt(1000)}}""",
131+
timestamp = System.currentTimeMillis(),
132+
durationMs = Random.nextLong(100, 2000),
133+
isSuccessful = successful,
134+
code = if (successful) 200 else 400,
135+
error = if (!successful) "Bad Request" else null,
136+
response = if (successful) """{"status": "success"}""" else null,
137+
requestSize = Random.nextLong(100, 5000)
138+
)
139+
}

debugMenu/src/main/java/com/tapadoo/debugmenu/DebugMenu.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ fun DebugMenuOverlay(
6060

6161

6262
var showContent by remember { mutableStateOf(false) }
63+
val scope = rememberCoroutineScope()
64+
var selected by remember { mutableStateOf<DebugMenuModule>(modules.first()) }
65+
val selectedIndex by remember { derivedStateOf { modules.indexOf(selected) } }
66+
6367

6468
// Shake detector
6569
if (enableShake) {
@@ -91,9 +95,6 @@ fun DebugMenuOverlay(
9195
}
9296
}
9397
if (showContent) {
94-
val scope = rememberCoroutineScope()
95-
var selected by remember { mutableStateOf<DebugMenuModule>(modules.first()) }
96-
val selectedIndex by remember { derivedStateOf { modules.indexOf(selected) } }
9798

9899
ModalBottomSheet(
99100
onDismissRequest = {

debugMenu/src/main/java/com/tapadoo/debugmenu/analytics/AnalyticsModule.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import androidx.compose.runtime.Composable
44
import com.tapadoo.debugmenu.module.DebugMenuModule
55
import com.tapadoo.debugmenu.ui.AnalyticsScreen
66

7-
class AnalyticsModule : DebugMenuModule{
7+
class AnalyticsModule : DebugMenuModule {
88

99
override val title = "Analytics"
1010

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.tapadoo.debugmenu.network
2+
3+
import androidx.compose.runtime.mutableStateListOf
4+
import androidx.compose.runtime.snapshots.SnapshotStateList
5+
6+
7+
data class DebugNetworkRequest(
8+
val url: String,
9+
val method: String,
10+
val headers: Map<String, String>,
11+
val responseHeaders: Map<String, String>,
12+
val body: String,
13+
val timestamp: Long,
14+
val durationMs: Long,
15+
val isSuccessful: Boolean,
16+
val code: Int,
17+
val error: String? = null,
18+
val response: String? = null,
19+
val requestSize: Long = 0,
20+
) {
21+
companion object
22+
}
23+
24+
25+
object DebugNetworkEvents {
26+
val events: SnapshotStateList<DebugNetworkRequest> = mutableStateListOf()
27+
28+
fun addEvent(event: DebugNetworkRequest) = events.add(event)
29+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.tapadoo.debugmenu.network
2+
3+
import androidx.activity.compose.BackHandler
4+
import androidx.compose.foundation.ExperimentalFoundationApi
5+
import androidx.compose.foundation.background
6+
import androidx.compose.foundation.layout.Arrangement
7+
import androidx.compose.foundation.layout.Box
8+
import androidx.compose.foundation.layout.Row
9+
import androidx.compose.foundation.layout.fillMaxSize
10+
import androidx.compose.foundation.layout.fillMaxWidth
11+
import androidx.compose.foundation.layout.padding
12+
import androidx.compose.foundation.lazy.LazyColumn
13+
import androidx.compose.foundation.lazy.items
14+
import androidx.compose.material.icons.Icons
15+
import androidx.compose.material.icons.outlined.Delete
16+
import androidx.compose.material3.Icon
17+
import androidx.compose.material3.IconButton
18+
import androidx.compose.material3.MaterialTheme
19+
import androidx.compose.runtime.Composable
20+
import androidx.compose.runtime.getValue
21+
import androidx.compose.runtime.mutableStateOf
22+
import androidx.compose.runtime.remember
23+
import androidx.compose.runtime.setValue
24+
import androidx.compose.ui.Modifier
25+
import androidx.compose.ui.unit.dp
26+
import com.tapadoo.debugmenu.module.DebugMenuModule
27+
28+
29+
class NetworkModule : DebugMenuModule {
30+
override val title: String = "Network"
31+
32+
@OptIn(ExperimentalFoundationApi::class)
33+
@Composable
34+
override fun Content() {
35+
NetworkScreen()
36+
}
37+
}

0 commit comments

Comments
 (0)