diff --git a/build.gradle b/build.gradle
index 2b72d2e..74aff00 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- ext.kotlin_version = "1.5.0"
+ ext.kotlin_version = "1.5.21"
ext.lifecycle_version = "2.3.1"
ext.coroutines_version = "1.4.3"
@@ -11,7 +11,7 @@ buildscript {
}
dependencies {
- classpath "com.android.tools.build:gradle:4.2.1"
+ classpath "com.android.tools.build:gradle:7.0.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath("org.jlleitschuh.gradle:ktlint-gradle:10.0.0")
diff --git a/common/.gitignore b/common/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/common/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/common/build.gradle b/common/build.gradle
new file mode 100644
index 0000000..5ae51d6
--- /dev/null
+++ b/common/build.gradle
@@ -0,0 +1,47 @@
+plugins {
+ id 'com.android.library'
+ id 'kotlin-android'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ kotlinOptions.jvmTarget = '1.8'
+
+ buildFeatures {
+ buildConfig false
+ viewBinding true
+ }
+}
+
+dependencies {
+
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+ implementation 'androidx.core:core-ktx:1.6.0'
+ implementation 'androidx.appcompat:appcompat:1.3.0'
+ implementation 'com.google.android.material:material:1.4.0'
+ testImplementation 'junit:junit:4.+'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+
+ implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
+
+ implementation 'io.reactivex.rxjava3:rxjava:3.0.12'
+}
\ No newline at end of file
diff --git a/common/consumer-rules.pro b/common/consumer-rules.pro
new file mode 100644
index 0000000..e69de29
diff --git a/common/proguard-rules.pro b/common/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/common/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/common/src/main/AndroidManifest.xml b/common/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..cf17631
--- /dev/null
+++ b/common/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/common/src/main/java/com/trendyol/devtools/common/BaseViewModel.kt b/common/src/main/java/com/trendyol/devtools/common/BaseViewModel.kt
new file mode 100644
index 0000000..5b5793a
--- /dev/null
+++ b/common/src/main/java/com/trendyol/devtools/common/BaseViewModel.kt
@@ -0,0 +1,14 @@
+package com.trendyol.devtools.common
+
+import androidx.lifecycle.ViewModel
+import io.reactivex.rxjava3.disposables.CompositeDisposable
+
+open class BaseViewModel : ViewModel() {
+
+ protected val disposable = CompositeDisposable()
+
+ override fun onCleared() {
+ disposable.dispose()
+ super.onCleared()
+ }
+}
diff --git a/dev-tools/src/main/java/com/trendyol/devtools/internal/fragment/FragmentViewBindingDelegate.kt b/common/src/main/java/com/trendyol/devtools/common/FragmentViewBindingDelegate.kt
similarity index 97%
rename from dev-tools/src/main/java/com/trendyol/devtools/internal/fragment/FragmentViewBindingDelegate.kt
rename to common/src/main/java/com/trendyol/devtools/common/FragmentViewBindingDelegate.kt
index 41a5152..ba0d062 100644
--- a/dev-tools/src/main/java/com/trendyol/devtools/internal/fragment/FragmentViewBindingDelegate.kt
+++ b/common/src/main/java/com/trendyol/devtools/common/FragmentViewBindingDelegate.kt
@@ -1,4 +1,4 @@
-package com.trendyol.devtools.internal.fragment
+package com.trendyol.devtools.common
// https://github.com/Zhuinden/fragmentviewbindingdelegate-kt
diff --git a/dev-tools/src/main/java/com/trendyol/devtools/internal/util/SingleLiveEvent.kt b/common/src/main/java/com/trendyol/devtools/common/SingleLiveEvent.kt
similarity index 93%
rename from dev-tools/src/main/java/com/trendyol/devtools/internal/util/SingleLiveEvent.kt
rename to common/src/main/java/com/trendyol/devtools/common/SingleLiveEvent.kt
index a81456d..0f6650a 100644
--- a/dev-tools/src/main/java/com/trendyol/devtools/internal/util/SingleLiveEvent.kt
+++ b/common/src/main/java/com/trendyol/devtools/common/SingleLiveEvent.kt
@@ -1,4 +1,4 @@
-package com.trendyol.devtools.internal.util
+package com.trendyol.devtools.common
import androidx.annotation.MainThread
import androidx.annotation.Nullable
@@ -19,7 +19,7 @@ import java.util.concurrent.atomic.AtomicBoolean
*
* see JoaquimLey/SingleLiveEvent.kt
*/
-internal class SingleLiveEvent : MutableLiveData() {
+class SingleLiveEvent : MutableLiveData() {
private val mPending = AtomicBoolean(false)
diff --git a/common/src/main/res/values/styles.xml b/common/src/main/res/values/styles.xml
new file mode 100644
index 0000000..5e96784
--- /dev/null
+++ b/common/src/main/res/values/styles.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/dev-tools/build.gradle b/dev-tools/build.gradle
index cba711d..80332eb 100644
--- a/dev-tools/build.gradle
+++ b/dev-tools/build.gradle
@@ -28,13 +28,6 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
- kotlinOptions {
- jvmTarget = '1.8'
- }
buildFeatures {
buildConfig false
@@ -44,17 +37,21 @@ android {
dependencies {
+ implementation project(":common")
+ implementation project(":http-debug")
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
- implementation 'androidx.core:core-ktx:1.3.2'
- implementation 'androidx.appcompat:appcompat:1.2.0'
- implementation 'com.google.android.material:material:1.3.0'
- implementation 'androidx.activity:activity-ktx:1.2.3'
- implementation "androidx.fragment:fragment-ktx:1.3.5"
+ implementation 'androidx.core:core-ktx:1.6.0'
+ implementation 'androidx.appcompat:appcompat:1.3.1'
+ implementation 'androidx.recyclerview:recyclerview:1.2.1'
+ implementation 'com.google.android.material:material:1.4.0'
+ implementation 'androidx.activity:activity-ktx:1.2.4'
+ implementation "androidx.fragment:fragment-ktx:1.3.6"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
- implementation 'com.github.Trendyol.android-ui-components:dialogs:dialogs-1.2.1-viewbinding'
+ implementation 'com.github.Trendyol.android-ui-components:dialogs:dialogs-1.2.4'
implementation 'io.reactivex.rxjava3:rxjava:3.0.12'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
diff --git a/dev-tools/src/main/java/com/trendyol/devtools/TrendyolDevTools.kt b/dev-tools/src/main/java/com/trendyol/devtools/TrendyolDevTools.kt
index 1bc3143..ef40df8 100644
--- a/dev-tools/src/main/java/com/trendyol/devtools/TrendyolDevTools.kt
+++ b/dev-tools/src/main/java/com/trendyol/devtools/TrendyolDevTools.kt
@@ -3,6 +3,7 @@ package com.trendyol.devtools
import android.app.Application
import android.content.Intent
import androidx.lifecycle.LiveData
+import com.trendyol.devtools.httpdebug.HttpDebug
import com.trendyol.devtools.internal.debugmenu.DebugActionItem
import com.trendyol.devtools.internal.debugmenu.DebugMenuUseCase
import com.trendyol.devtools.internal.di.ContextContainer
@@ -18,6 +19,7 @@ object TrendyolDevTools {
fun init(application: Application) {
ContextContainer.setContext(application)
+ HttpDebug.init(application)
debugMenuUseCase = ContextContainer.debugMenuContainer.debugMenuUseCase
environmentsUseCase = ContextContainer.environmentsContainer.environmentUseCase
DevToolsService.initializeService(application)
diff --git a/dev-tools/src/main/java/com/trendyol/devtools/internal/debugmenu/DebugMenuFragment.kt b/dev-tools/src/main/java/com/trendyol/devtools/internal/debugmenu/DebugMenuFragment.kt
index 21706cb..1701499 100644
--- a/dev-tools/src/main/java/com/trendyol/devtools/internal/debugmenu/DebugMenuFragment.kt
+++ b/dev-tools/src/main/java/com/trendyol/devtools/internal/debugmenu/DebugMenuFragment.kt
@@ -5,9 +5,9 @@ import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import com.trendyol.devtools.R
+import com.trendyol.devtools.common.viewBinding
import com.trendyol.devtools.databinding.DevToolsFragmentDebugMenuBinding
import com.trendyol.devtools.internal.di.ContextContainer
-import com.trendyol.devtools.internal.fragment.viewBinding
internal class DebugMenuFragment : Fragment(R.layout.dev_tools_fragment_debug_menu) {
diff --git a/dev-tools/src/main/java/com/trendyol/devtools/internal/debugmenu/DebugMenuUseCase.kt b/dev-tools/src/main/java/com/trendyol/devtools/internal/debugmenu/DebugMenuUseCase.kt
index ca5eb1c..059a169 100644
--- a/dev-tools/src/main/java/com/trendyol/devtools/internal/debugmenu/DebugMenuUseCase.kt
+++ b/dev-tools/src/main/java/com/trendyol/devtools/internal/debugmenu/DebugMenuUseCase.kt
@@ -2,7 +2,7 @@ package com.trendyol.devtools.internal.debugmenu
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
-import com.trendyol.devtools.internal.util.SingleLiveEvent
+import com.trendyol.devtools.common.SingleLiveEvent
internal class DebugMenuUseCase constructor(
private val clickEvent: SingleLiveEvent = SingleLiveEvent(),
diff --git a/dev-tools/src/main/java/com/trendyol/devtools/internal/domain/EnvironmentUseCase.kt b/dev-tools/src/main/java/com/trendyol/devtools/internal/domain/EnvironmentUseCase.kt
index f2bde43..e548acc 100644
--- a/dev-tools/src/main/java/com/trendyol/devtools/internal/domain/EnvironmentUseCase.kt
+++ b/dev-tools/src/main/java/com/trendyol/devtools/internal/domain/EnvironmentUseCase.kt
@@ -3,7 +3,7 @@ package com.trendyol.devtools.internal.domain
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.trendyol.devtools.internal.data.EnvironmentRepository
-import com.trendyol.devtools.internal.util.SingleLiveEvent
+import com.trendyol.devtools.common.SingleLiveEvent
import com.trendyol.devtools.model.DefaultEnvironments
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.schedulers.Schedulers
diff --git a/dev-tools/src/main/java/com/trendyol/devtools/internal/main/MainFragment.kt b/dev-tools/src/main/java/com/trendyol/devtools/internal/main/MainFragment.kt
index 8af2d06..e6e37ad 100644
--- a/dev-tools/src/main/java/com/trendyol/devtools/internal/main/MainFragment.kt
+++ b/dev-tools/src/main/java/com/trendyol/devtools/internal/main/MainFragment.kt
@@ -6,10 +6,11 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import com.infinum.dbinspector.DbInspector
import com.trendyol.devtools.R
+import com.trendyol.devtools.common.viewBinding
import com.trendyol.devtools.databinding.DevToolsFragmentMainBinding
+import com.trendyol.devtools.httpdebug.HttpDebug
import com.trendyol.devtools.internal.debugmenu.DebugMenuFragment
import com.trendyol.devtools.internal.di.ContextContainer
-import com.trendyol.devtools.internal.fragment.viewBinding
import com.trendyol.uicomponents.dialogs.selectionDialog
internal class MainFragment : Fragment(R.layout.dev_tools_fragment_main) {
@@ -39,6 +40,10 @@ internal class MainFragment : Fragment(R.layout.dev_tools_fragment_main) {
buttonInspectDatabase.setOnClickListener {
DbInspector.show()
}
+ buttonHttpDebug.setOnClickListener {
+ HttpDebug.enable()
+ HttpDebug.show()
+ }
}
private fun navigateToDebugMenu() {
diff --git a/dev-tools/src/main/java/com/trendyol/devtools/internal/main/MainViewModel.kt b/dev-tools/src/main/java/com/trendyol/devtools/internal/main/MainViewModel.kt
index 1589a9b..d834580 100644
--- a/dev-tools/src/main/java/com/trendyol/devtools/internal/main/MainViewModel.kt
+++ b/dev-tools/src/main/java/com/trendyol/devtools/internal/main/MainViewModel.kt
@@ -3,7 +3,7 @@ package com.trendyol.devtools.internal.main
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import com.trendyol.devtools.internal.domain.EnvironmentUseCase
-import com.trendyol.devtools.internal.util.SingleLiveEvent
+import com.trendyol.devtools.common.SingleLiveEvent
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
internal class MainViewModel(private val environmentUseCase: EnvironmentUseCase) : ViewModel() {
diff --git a/dev-tools/src/main/res/layout/dev_tools_fragment_main.xml b/dev-tools/src/main/res/layout/dev_tools_fragment_main.xml
index 08b5541..70a4b83 100644
--- a/dev-tools/src/main/res/layout/dev_tools_fragment_main.xml
+++ b/dev-tools/src/main/res/layout/dev_tools_fragment_main.xml
@@ -41,6 +41,16 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/buttonChangeEnvironment" />
+
+
+ app:layout_constraintTop_toBottomOf="@+id/buttonHttpDebug" />
\ No newline at end of file
diff --git a/dev-tools/src/main/res/values/strings.xml b/dev-tools/src/main/res/values/strings.xml
index a243053..c8fc576 100644
--- a/dev-tools/src/main/res/values/strings.xml
+++ b/dev-tools/src/main/res/values/strings.xml
@@ -7,4 +7,5 @@
Debug Page
Inspect Database
Select Environment
+ Http Debug
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 8320ca7..cb29fa8 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon May 10 14:20:15 TRT 2021
+#Thu Jul 29 00:57:25 TRT 2021
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
diff --git a/http-debug/.gitignore b/http-debug/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/http-debug/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/http-debug/build.gradle b/http-debug/build.gradle
new file mode 100644
index 0000000..decbe61
--- /dev/null
+++ b/http-debug/build.gradle
@@ -0,0 +1,54 @@
+plugins {
+ id 'com.android.library'
+ id 'kotlin-android'
+}
+
+android {
+ compileSdkVersion 30
+ buildToolsVersion "30.0.3"
+
+ defaultConfig {
+ minSdkVersion 21
+ targetSdkVersion 30
+ versionCode 1
+ versionName "0.1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions.jvmTarget = '1.8'
+
+ buildFeatures {
+ buildConfig false
+ viewBinding true
+ }
+}
+
+dependencies {
+
+ implementation project(":common")
+
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
+
+ implementation 'androidx.core:core-ktx:1.6.0'
+ implementation 'androidx.appcompat:appcompat:1.3.1'
+ implementation 'androidx.fragment:fragment-ktx:1.3.6'
+
+ implementation 'com.google.android.material:material:1.4.0'
+
+ implementation 'io.reactivex.rxjava3:rxjava:3.0.12'
+ implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
+
+ implementation 'com.squareup.okhttp3:okhttp:4.9.1'
+}
\ No newline at end of file
diff --git a/http-debug/consumer-rules.pro b/http-debug/consumer-rules.pro
new file mode 100644
index 0000000..e69de29
diff --git a/http-debug/proguard-rules.pro b/http-debug/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/http-debug/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/http-debug/src/main/AndroidManifest.xml b/http-debug/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..3c5249b
--- /dev/null
+++ b/http-debug/src/main/AndroidManifest.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/HttpDebug.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/HttpDebug.kt
new file mode 100644
index 0000000..e87230d
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/HttpDebug.kt
@@ -0,0 +1,30 @@
+package com.trendyol.devtools.httpdebug
+
+import android.app.Application
+import android.content.Intent
+import com.trendyol.devtools.httpdebug.internal.di.ContextContainer
+import com.trendyol.devtools.httpdebug.internal.di.MainContainer
+import com.trendyol.devtools.httpdebug.internal.ui.HttpDebugActivity
+
+object HttpDebug {
+
+ private val manipulatorUseCase = MainContainer.manipulatorUseCase
+
+ fun init(application: Application) {
+ ContextContainer.setContext(application)
+ }
+
+ fun show() {
+ val context = ContextContainer.getContext()
+ val intent = Intent(context, HttpDebugActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ context.startActivity(intent)
+ }
+
+ fun enable() {
+ manipulatorUseCase.setToggleToTrue()
+ }
+
+ fun disable() {
+ manipulatorUseCase.setToggleToFalse()
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/HttpDebugInterceptor.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/HttpDebugInterceptor.kt
new file mode 100644
index 0000000..33df671
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/HttpDebugInterceptor.kt
@@ -0,0 +1,21 @@
+package com.trendyol.devtools.httpdebug
+
+import com.trendyol.devtools.httpdebug.internal.di.MainContainer
+import com.trendyol.devtools.httpdebug.internal.domain.IdGeneratorUseCase
+import com.trendyol.devtools.httpdebug.internal.domain.ManipulatorUseCase
+import okhttp3.Interceptor
+import okhttp3.Response
+
+class HttpDebugInterceptor : Interceptor {
+
+ private val useCase: ManipulatorUseCase = MainContainer.manipulatorUseCase
+ private val requestIdGeneratorUseCase: IdGeneratorUseCase = MainContainer.idGeneratorUseCase
+
+ override fun intercept(chain: Interceptor.Chain): Response {
+ val id: String = requestIdGeneratorUseCase.generateId(chain.request())
+
+ val updatedRequest = useCase.newRequest(chain.request(), id)
+
+ return useCase.newResponse(chain.proceed(updatedRequest), id)
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/ContextContainer.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/ContextContainer.kt
new file mode 100644
index 0000000..1c99d23
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/ContextContainer.kt
@@ -0,0 +1,24 @@
+package com.trendyol.devtools.httpdebug.internal.di
+
+import android.annotation.SuppressLint
+import android.content.Context
+
+@SuppressLint("StaticFieldLeak")
+internal object ContextContainer {
+
+ private lateinit var context: Context
+
+ fun getContext(): Context =
+ if (::context.isInitialized) {
+ context
+ } else {
+ throw NullPointerException(
+ "Dev Tools library is not initialized, please call TrendyolDevTools.init(Application) on " +
+ "Application.onCreate to use Trendyol Dev Tools."
+ )
+ }
+
+ fun setContext(context: Context) {
+ this.context = context
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/DetailContainer.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/DetailContainer.kt
new file mode 100644
index 0000000..85d6d84
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/DetailContainer.kt
@@ -0,0 +1,16 @@
+package com.trendyol.devtools.httpdebug.internal.di
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.trendyol.devtools.httpdebug.internal.ui.detail.DetailViewModel
+
+internal class DetailContainer {
+
+ internal inner class DetailViewModelFactory : ViewModelProvider.Factory {
+
+ @Suppress("UNCHECKED_CAST")
+ override fun create(modelClass: Class): T {
+ return DetailViewModel(MainContainer.manipulatorUseCase) as T
+ }
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/MainContainer.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/MainContainer.kt
new file mode 100644
index 0000000..a784263
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/MainContainer.kt
@@ -0,0 +1,11 @@
+package com.trendyol.devtools.httpdebug.internal.di
+
+import com.trendyol.devtools.httpdebug.internal.domain.IdGeneratorUseCase
+import com.trendyol.devtools.httpdebug.internal.domain.ManipulatorUseCase
+
+internal object MainContainer {
+
+ val manipulatorUseCase by lazy { ManipulatorUseCase() }
+ val idGeneratorUseCase by lazy { IdGeneratorUseCase() }
+ val requestListContainer by lazy { RequestListContainer() }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/RequestListContainer.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/RequestListContainer.kt
new file mode 100644
index 0000000..00ff273
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/RequestListContainer.kt
@@ -0,0 +1,23 @@
+package com.trendyol.devtools.httpdebug.internal.di
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.trendyol.devtools.httpdebug.internal.domain.GetActiveRequestsUseCase
+import com.trendyol.devtools.httpdebug.internal.domain.SkipRequestUseCase
+import com.trendyol.devtools.httpdebug.internal.ui.list.ListViewModel
+
+internal class RequestListContainer {
+
+ val getActiveRequestsUseCase by lazy { GetActiveRequestsUseCase(MainContainer.manipulatorUseCase) }
+ val skipRequestUseCase by lazy { SkipRequestUseCase(MainContainer.manipulatorUseCase) }
+
+ internal inner class ListViewModelFactory : ViewModelProvider.Factory {
+
+ @Suppress("UNCHECKED_CAST")
+ override fun create(modelClass: Class): T =
+ ListViewModel(
+ getActiveRequestsUseCase,
+ skipRequestUseCase
+ ) as T
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/RequestTabContainer.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/RequestTabContainer.kt
new file mode 100644
index 0000000..0d97f8f
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/RequestTabContainer.kt
@@ -0,0 +1,19 @@
+package com.trendyol.devtools.httpdebug.internal.di
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.trendyol.devtools.httpdebug.internal.domain.GetRequestUseCase
+import com.trendyol.devtools.httpdebug.internal.ui.detail.request.RequestTabViewModel
+
+internal class RequestTabContainer {
+
+ private val getRequestUseCase: GetRequestUseCase by lazy { GetRequestUseCase(MainContainer.manipulatorUseCase) }
+
+ internal inner class RequestTabViewModelFactory : ViewModelProvider.Factory {
+
+ @Suppress("UNCHECKED_CAST")
+ override fun create(modelClass: Class): T {
+ return RequestTabViewModel(getRequestUseCase) as T
+ }
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/ResponseTabContainer.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/ResponseTabContainer.kt
new file mode 100644
index 0000000..e3a6cc1
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/di/ResponseTabContainer.kt
@@ -0,0 +1,20 @@
+package com.trendyol.devtools.httpdebug.internal.di
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.trendyol.devtools.httpdebug.internal.domain.GetRequestUseCase
+import com.trendyol.devtools.httpdebug.internal.domain.GetResponseUseCase
+import com.trendyol.devtools.httpdebug.internal.ui.detail.response.ResponseTabViewModel
+
+internal class ResponseTabContainer {
+
+ private val getResponseUseCase: GetResponseUseCase by lazy { GetResponseUseCase(MainContainer.manipulatorUseCase) }
+
+ internal inner class ResponseTabViewModelFactory : ViewModelProvider.Factory {
+
+ @Suppress("UNCHECKED_CAST")
+ override fun create(modelClass: Class): T {
+ return ResponseTabViewModel(getResponseUseCase) as T
+ }
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/GetActiveRequestsUseCase.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/GetActiveRequestsUseCase.kt
new file mode 100644
index 0000000..faaf884
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/GetActiveRequestsUseCase.kt
@@ -0,0 +1,23 @@
+package com.trendyol.devtools.httpdebug.internal.domain
+
+import com.trendyol.devtools.httpdebug.internal.model.RequestResponse
+import com.trendyol.devtools.httpdebug.internal.model.State
+import io.reactivex.rxjava3.core.Observable
+import io.reactivex.rxjava3.schedulers.Schedulers
+
+internal class GetActiveRequestsUseCase(private val manipulatorUseCase: ManipulatorUseCase) {
+
+ fun getActiveRequests(): Observable> {
+ return manipulatorUseCase
+ .requestsSubject
+ .subscribeOn(Schedulers.io())
+ .concatMap {
+ Observable.fromIterable(it.values)
+ .filter { requestResponse ->
+ requestResponse.response.state == State.BLOCKED
+ }
+ .toList()
+ .toObservable()
+ }
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/GetRequestUseCase.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/GetRequestUseCase.kt
new file mode 100644
index 0000000..606b561
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/GetRequestUseCase.kt
@@ -0,0 +1,25 @@
+package com.trendyol.devtools.httpdebug.internal.domain
+
+import com.trendyol.devtools.httpdebug.internal.model.HttpDebugRequest
+import io.reactivex.rxjava3.core.Maybe
+import io.reactivex.rxjava3.core.Observable
+import io.reactivex.rxjava3.schedulers.Schedulers
+
+internal class GetRequestUseCase(private val manipulatorUseCase: ManipulatorUseCase) {
+
+ fun getRequest(id: String): Observable {
+ return manipulatorUseCase
+ .requestsSubject
+ .subscribeOn(Schedulers.io())
+ .flatMapMaybe {
+ if (it[id] != null) {
+ Maybe.just(it[id])
+ } else {
+ Maybe.empty()
+ }
+ }
+ .map {
+ it?.request
+ }
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/GetResponseUseCase.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/GetResponseUseCase.kt
new file mode 100644
index 0000000..727f34c
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/GetResponseUseCase.kt
@@ -0,0 +1,25 @@
+package com.trendyol.devtools.httpdebug.internal.domain
+
+import com.trendyol.devtools.httpdebug.internal.model.HttpDebugResponse
+import io.reactivex.rxjava3.core.Maybe
+import io.reactivex.rxjava3.core.Observable
+import io.reactivex.rxjava3.schedulers.Schedulers
+
+internal class GetResponseUseCase(private val manipulatorUseCase: ManipulatorUseCase) {
+
+ fun getResponse(id: String): Observable {
+ return manipulatorUseCase
+ .requestsSubject
+ .subscribeOn(Schedulers.io())
+ .flatMapMaybe {
+ if (it[id] != null) {
+ Maybe.just(it[id])
+ } else {
+ Maybe.empty()
+ }
+ }
+ .map {
+ it?.response
+ }
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/IdGeneratorUseCase.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/IdGeneratorUseCase.kt
new file mode 100644
index 0000000..374e789
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/IdGeneratorUseCase.kt
@@ -0,0 +1,8 @@
+package com.trendyol.devtools.httpdebug.internal.domain
+
+import okhttp3.Request
+
+internal class IdGeneratorUseCase {
+
+ fun generateId(request: Request): String = TODO("generate id with request and timestamp")
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/ManipulatorUseCase.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/ManipulatorUseCase.kt
new file mode 100644
index 0000000..463e916
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/ManipulatorUseCase.kt
@@ -0,0 +1,63 @@
+package com.trendyol.devtools.httpdebug.internal.domain
+
+import com.trendyol.devtools.httpdebug.internal.model.HttpDebugRequest
+import com.trendyol.devtools.httpdebug.internal.model.HttpDebugResponse
+import com.trendyol.devtools.httpdebug.internal.model.RequestResponse
+import com.trendyol.devtools.httpdebug.internal.model.State
+import io.reactivex.rxjava3.subjects.BehaviorSubject
+import okhttp3.Request
+import okhttp3.Response
+
+internal class ManipulatorUseCase {
+
+ private var toggle: Boolean = false
+ val requestsSubject: BehaviorSubject> =
+ BehaviorSubject.createDefault(mutableMapOf())
+
+ fun newRequest(request: Request, id: String): Request {
+ requestsSubject.value[id] = RequestResponse(
+ id = id,
+ request = HttpDebugRequest(request, if (toggle) State.BLOCKED else State.PASS),
+ response = HttpDebugResponse(null, State.BLOCKED)
+ )
+ requestsSubject.onNext(requestsSubject.value)
+
+ while (requestsSubject.value[id]?.request?.state == State.BLOCKED) {
+ Thread.sleep(100)
+ }
+
+ return requestsSubject.value[id]?.request?.request ?: request
+ }
+
+ fun newResponse(response: Response, id: String): Response {
+ requestsSubject.value[id]?.response =
+ HttpDebugResponse(response, if (toggle) State.BLOCKED else State.PASS)
+
+ while (requestsSubject.value[id]?.response?.state == State.BLOCKED) {
+ Thread.sleep(100)
+ }
+
+ return requestsSubject.value[id]?.response?.response ?: response
+ }
+
+ fun setToggleToTrue() {
+ toggle = true
+ }
+
+ fun setToggleToFalse() {
+ toggle = false
+ requestsSubject.value.clear()
+ }
+
+ fun interceptRequest(id: String, modifyBlock: (Request) -> Request) {
+ requestsSubject.value[id]?.request?.request = modifyBlock.invoke(requestsSubject.value[id]!!.request.request)
+ requestsSubject.value[id]?.request?.state = State.SENT
+ }
+
+ fun interceptResponse(id: String, modifyBlock: (Response) -> Response) {
+ requestsSubject.value[id]?.response?.response =
+ modifyBlock.invoke(requestsSubject.value[id]!!.response.response!!)
+ requestsSubject.value[id]?.request?.state = State.SENT
+ requestsSubject.value[id]?.response?.state = State.SENT
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/SkipRequestUseCase.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/SkipRequestUseCase.kt
new file mode 100644
index 0000000..ce588d8
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/domain/SkipRequestUseCase.kt
@@ -0,0 +1,19 @@
+package com.trendyol.devtools.httpdebug.internal.domain
+
+internal class SkipRequestUseCase(
+ private val manipulatorUseCase: ManipulatorUseCase
+) {
+
+ fun skipRequest(id: String, isRequest: Boolean) {
+ if (isRequest) {
+ manipulatorUseCase.interceptRequest(id) { it }
+ } else {
+ manipulatorUseCase.interceptResponse(id) { it }
+ }
+ TODO("skip request with given id $id")
+ }
+
+ fun skipAllRequests() {
+ TODO("skip all requests")
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/model/HttpDebugRequest.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/model/HttpDebugRequest.kt
new file mode 100644
index 0000000..3d6834e
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/model/HttpDebugRequest.kt
@@ -0,0 +1,13 @@
+package com.trendyol.devtools.httpdebug.internal.model
+
+import okhttp3.Request
+import okhttp3.RequestBody
+
+internal data class HttpDebugRequest(var request: Request, var state: State) {
+
+ val requestUrl: String = request.url.toString()
+ val requestMethod: String = request.method
+ val requestBody: RequestBody? = request.body
+
+ fun getHeaders(): Map> = request.headers.toMultimap()
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/model/HttpDebugResponse.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/model/HttpDebugResponse.kt
new file mode 100644
index 0000000..6e4350c
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/model/HttpDebugResponse.kt
@@ -0,0 +1,5 @@
+package com.trendyol.devtools.httpdebug.internal.model
+
+import okhttp3.Response
+
+internal data class HttpDebugResponse(var response: Response?, var state: State)
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/model/RequestResponse.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/model/RequestResponse.kt
new file mode 100644
index 0000000..265e601
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/model/RequestResponse.kt
@@ -0,0 +1,12 @@
+package com.trendyol.devtools.httpdebug.internal.model
+
+import android.view.View
+
+internal data class RequestResponse(
+ val id: String,
+ var request: HttpDebugRequest,
+ var response: HttpDebugResponse
+) {
+
+ fun getResponseCodeVisibility(): Int = if (response.response != null) View.VISIBLE else View.GONE
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/model/State.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/model/State.kt
new file mode 100644
index 0000000..2366b3f
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/model/State.kt
@@ -0,0 +1,5 @@
+package com.trendyol.devtools.httpdebug.internal.model
+
+internal enum class State {
+ BLOCKED, PASS, SENT
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/HttpDebugActivity.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/HttpDebugActivity.kt
new file mode 100644
index 0000000..5269297
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/HttpDebugActivity.kt
@@ -0,0 +1,44 @@
+package com.trendyol.devtools.httpdebug.internal.ui
+
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import androidx.fragment.app.Fragment
+import com.trendyol.devtools.httpdebug.R
+import com.trendyol.devtools.httpdebug.internal.ui.list.ListFragment
+
+private const val KEY_BACKSTACK = "http_debug_backstack"
+
+internal class HttpDebugActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.dev_tools_http_debug_activity)
+
+ if (savedInstanceState == null) {
+ initializeContainer()
+ }
+ }
+
+ fun openFragment(fragment: Fragment) {
+ supportFragmentManager
+ .beginTransaction()
+ .replace(R.id.dev_tools_http_debug_container, fragment)
+ .addToBackStack(KEY_BACKSTACK)
+ .commit()
+ }
+
+ private fun initializeContainer() {
+ supportFragmentManager
+ .beginTransaction()
+ .add(R.id.dev_tools_http_debug_container, ListFragment())
+ .commit()
+ }
+
+ override fun onBackPressed() {
+ if (supportFragmentManager.backStackEntryCount > 0) {
+ supportFragmentManager.popBackStack()
+ } else {
+ super.onBackPressed()
+ }
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/DetailFragment.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/DetailFragment.kt
new file mode 100644
index 0000000..728cad6
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/DetailFragment.kt
@@ -0,0 +1,74 @@
+package com.trendyol.devtools.httpdebug.internal.ui.detail
+
+import android.os.Bundle
+import android.view.View
+import androidx.core.os.bundleOf
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import com.google.android.material.tabs.TabLayout
+import com.trendyol.devtools.common.viewBinding
+import com.trendyol.devtools.httpdebug.R
+import com.trendyol.devtools.httpdebug.databinding.DevToolsHttpDebugFragmentDetailBinding
+import com.trendyol.devtools.httpdebug.internal.di.DetailContainer
+import com.trendyol.devtools.httpdebug.internal.ui.detail.request.RequestTabFragment
+import com.trendyol.devtools.httpdebug.internal.ui.detail.response.ResponseTabFragment
+
+internal class DetailFragment : Fragment(R.layout.dev_tools_http_debug_fragment_detail) {
+
+ private val binding by viewBinding(DevToolsHttpDebugFragmentDetailBinding::bind)
+ private val viewModel by viewModels { DetailContainer().DetailViewModelFactory() }
+ private val id by lazy { requireArguments().getString(KEY_ID)!! }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ binding.devToolsHttpDebugFabDetail.setOnClickListener {
+ viewModel.skipRequest(id, binding.devToolsHttpDebugTabLayoutDetail.selectedTabPosition == 0)
+ }
+
+ binding.devToolsHttpDebugTabLayoutDetail.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
+ override fun onTabSelected(tab: TabLayout.Tab) {
+ when (tab) {
+ binding.devToolsHttpDebugTabLayoutDetail.getTabAt(0) -> openRequestTab()
+ binding.devToolsHttpDebugTabLayoutDetail.getTabAt(1) -> openResponseTab()
+ }
+ }
+
+ override fun onTabUnselected(tab: TabLayout.Tab?) {
+ // do nothing
+ }
+
+ override fun onTabReselected(tab: TabLayout.Tab?) {
+ // do nothing
+ }
+ })
+
+ if (savedInstanceState == null) {
+ openRequestTab()
+ }
+ }
+
+ private fun openRequestTab() {
+ childFragmentManager
+ .beginTransaction()
+ .replace(binding.devToolsHttpDebugContainerDetail.id, RequestTabFragment.newInstance(id))
+ .commit()
+ }
+
+ private fun openResponseTab() {
+ childFragmentManager
+ .beginTransaction()
+ .replace(binding.devToolsHttpDebugContainerDetail.id, ResponseTabFragment.newInstance(id))
+ .commit()
+ }
+
+ companion object {
+
+ private const val KEY_ID = "key_id"
+
+ fun newInstance(id: String): DetailFragment =
+ DetailFragment().apply {
+ arguments = bundleOf(KEY_ID to id)
+ }
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/DetailViewModel.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/DetailViewModel.kt
new file mode 100644
index 0000000..0fff169
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/DetailViewModel.kt
@@ -0,0 +1,15 @@
+package com.trendyol.devtools.httpdebug.internal.ui.detail
+
+import com.trendyol.devtools.common.BaseViewModel
+import com.trendyol.devtools.httpdebug.internal.domain.ManipulatorUseCase
+
+internal class DetailViewModel(private val manipulatorUseCase: ManipulatorUseCase) : BaseViewModel() {
+
+ fun skipRequest(id: String, isRequestTab: Boolean) {
+ if (isRequestTab) {
+ manipulatorUseCase.interceptRequest(id) { it }
+ } else {
+ manipulatorUseCase.interceptResponse(id) { it }
+ }
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/request/RequestTabFragment.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/request/RequestTabFragment.kt
new file mode 100644
index 0000000..bfdb42a
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/request/RequestTabFragment.kt
@@ -0,0 +1,40 @@
+package com.trendyol.devtools.httpdebug.internal.ui.detail.request
+
+import android.os.Bundle
+import android.view.View
+import androidx.core.os.bundleOf
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import com.trendyol.devtools.common.viewBinding
+import com.trendyol.devtools.httpdebug.R
+import com.trendyol.devtools.httpdebug.databinding.DevToolsHttpDebugFragmentRequestTabBinding
+import com.trendyol.devtools.httpdebug.internal.di.RequestTabContainer
+
+internal class RequestTabFragment : Fragment(R.layout.dev_tools_http_debug_fragment_request_tab) {
+
+ private val binding by viewBinding(DevToolsHttpDebugFragmentRequestTabBinding::bind)
+ private val viewModel by viewModels { RequestTabContainer().RequestTabViewModelFactory() }
+ private val id by lazy { requireArguments().getString(KEY_ID)!! }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ if (savedInstanceState == null) {
+ viewModel.getRequestDetails(id)
+ }
+
+ viewModel.getRequestLiveEvent().observe(viewLifecycleOwner) {
+ TODO("Bind")
+ }
+ }
+
+ companion object {
+
+ private const val KEY_ID = "key_id"
+
+ fun newInstance(id: String): RequestTabFragment =
+ RequestTabFragment().apply {
+ arguments = bundleOf(KEY_ID to id)
+ }
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/request/RequestTabViewModel.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/request/RequestTabViewModel.kt
new file mode 100644
index 0000000..d3b1830
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/request/RequestTabViewModel.kt
@@ -0,0 +1,22 @@
+package com.trendyol.devtools.httpdebug.internal.ui.detail.request
+
+import androidx.lifecycle.LiveData
+import com.trendyol.devtools.common.BaseViewModel
+import com.trendyol.devtools.common.SingleLiveEvent
+import com.trendyol.devtools.httpdebug.internal.domain.GetRequestUseCase
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
+
+internal class RequestTabViewModel(private val getRequestUseCase: GetRequestUseCase) : BaseViewModel() {
+
+ private val requestLiveEvent: SingleLiveEvent = SingleLiveEvent()
+
+ fun getRequestLiveEvent(): LiveData = requestLiveEvent
+
+ fun getRequestDetails(id: String) {
+ getRequestUseCase
+ .getRequest(id)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe { requestLiveEvent.value = RequestTabViewState(it) }
+ .also(disposable::add)
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/request/RequestTabViewState.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/request/RequestTabViewState.kt
new file mode 100644
index 0000000..7bc216f
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/request/RequestTabViewState.kt
@@ -0,0 +1,18 @@
+package com.trendyol.devtools.httpdebug.internal.ui.detail.request
+
+import android.content.Context
+import com.trendyol.devtools.httpdebug.R
+import com.trendyol.devtools.httpdebug.internal.model.HttpDebugRequest
+
+internal data class RequestTabViewState(private val request: HttpDebugRequest) {
+
+ fun getHeaders(): String = TODO()
+
+ fun getRequestBody(context: Context): String {
+ if (request.requestBody == null || request.requestBody.isDuplex() || request.requestBody.isOneShot() || request.requestBody.contentType()?.type != "text") {
+ return context.getString(R.string.dev_tools_http_debug_string_request_body_not_presentable)
+ }
+
+ TODO()
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/response/ResponseTabFragment.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/response/ResponseTabFragment.kt
new file mode 100644
index 0000000..1ea2eca
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/response/ResponseTabFragment.kt
@@ -0,0 +1,40 @@
+package com.trendyol.devtools.httpdebug.internal.ui.detail.response
+
+import android.os.Bundle
+import android.view.View
+import androidx.core.os.bundleOf
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import com.trendyol.devtools.common.viewBinding
+import com.trendyol.devtools.httpdebug.R
+import com.trendyol.devtools.httpdebug.databinding.DevToolsHttpDebugFragmentResponseTabBinding
+import com.trendyol.devtools.httpdebug.internal.di.ResponseTabContainer
+
+internal class ResponseTabFragment : Fragment(R.layout.dev_tools_http_debug_fragment_response_tab) {
+
+ private val binding by viewBinding(DevToolsHttpDebugFragmentResponseTabBinding::bind)
+ private val viewModel by viewModels { ResponseTabContainer().ResponseTabViewModelFactory() }
+ private val id by lazy { requireArguments().getString(KEY_ID)!! }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ if (savedInstanceState == null) {
+ viewModel.getResponse(id)
+ }
+
+ viewModel.getResponseLiveEvent().observe(viewLifecycleOwner) {
+ TODO("Bind")
+ }
+ }
+
+ companion object {
+
+ private const val KEY_ID = "key_id"
+
+ fun newInstance(id: String): ResponseTabFragment =
+ ResponseTabFragment().apply {
+ arguments = bundleOf(KEY_ID to id)
+ }
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/response/ResponseTabViewModel.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/response/ResponseTabViewModel.kt
new file mode 100644
index 0000000..bc8e60c
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/response/ResponseTabViewModel.kt
@@ -0,0 +1,22 @@
+package com.trendyol.devtools.httpdebug.internal.ui.detail.response
+
+import androidx.lifecycle.LiveData
+import com.trendyol.devtools.common.BaseViewModel
+import com.trendyol.devtools.common.SingleLiveEvent
+import com.trendyol.devtools.httpdebug.internal.domain.GetResponseUseCase
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
+
+internal class ResponseTabViewModel(private val getResponseUseCase: GetResponseUseCase) : BaseViewModel() {
+
+ private val responseLiveEvent: SingleLiveEvent = SingleLiveEvent()
+
+ fun getResponseLiveEvent(): LiveData = responseLiveEvent
+
+ fun getResponse(id: String) {
+ getResponseUseCase
+ .getResponse(id)
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe { responseLiveEvent.value = ResponseTabViewState(it) }
+ .also(disposable::add)
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/response/ResponseTabViewState.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/response/ResponseTabViewState.kt
new file mode 100644
index 0000000..48a90c7
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/detail/response/ResponseTabViewState.kt
@@ -0,0 +1,6 @@
+package com.trendyol.devtools.httpdebug.internal.ui.detail.response
+
+import com.trendyol.devtools.httpdebug.internal.model.HttpDebugResponse
+
+internal data class ResponseTabViewState(private val response: HttpDebugResponse) {
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/list/ListFragment.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/list/ListFragment.kt
new file mode 100644
index 0000000..f6db05c
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/list/ListFragment.kt
@@ -0,0 +1,62 @@
+package com.trendyol.devtools.httpdebug.internal.ui.list
+
+import android.os.Bundle
+import android.view.View
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.trendyol.devtools.common.viewBinding
+import com.trendyol.devtools.httpdebug.R
+import com.trendyol.devtools.httpdebug.databinding.DevToolsHttpDebugFragmentListBinding
+import com.trendyol.devtools.httpdebug.internal.di.MainContainer
+import com.trendyol.devtools.httpdebug.internal.ui.HttpDebugActivity
+import com.trendyol.devtools.httpdebug.internal.ui.detail.DetailFragment
+
+internal class ListFragment : Fragment(R.layout.dev_tools_http_debug_fragment_list) {
+
+ private val binding by viewBinding(DevToolsHttpDebugFragmentListBinding::bind)
+ private val viewModel by viewModels {
+ MainContainer.requestListContainer.ListViewModelFactory()
+ }
+ private val adapter by lazy {
+ RequestListAdapter { requestId ->
+ val detailFragment = DetailFragment.newInstance(requestId)
+ (requireActivity() as HttpDebugActivity).openFragment(detailFragment)
+ }
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ binding.devToolsHttpDebugFabSkipAllRequests.setOnClickListener { viewModel.skipAllRequests() }
+ binding.devToolsHttpDebugRecyclerRequests.adapter = adapter
+ val itemTouchHelper = object : ItemTouchHelper(
+ object : ItemTouchHelper.SimpleCallback(0, LEFT) {
+ override fun onMove(
+ recyclerView: RecyclerView,
+ viewHolder: RecyclerView.ViewHolder,
+ target: RecyclerView.ViewHolder
+ ): Boolean = true
+
+ override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
+ val requestId = adapter.currentList[viewHolder.adapterPosition].id
+ viewModel.skipRequest(requestId)
+ }
+ }
+ ) {
+ }
+
+ itemTouchHelper.attachToRecyclerView(binding.devToolsHttpDebugRecyclerRequests)
+
+ viewModel.getRequests()
+ viewModel.getRequestsLiveData().observe(viewLifecycleOwner) {
+ adapter.submitList(it)
+ if (it.isEmpty()) {
+ binding.devToolsHttpDebugFabSkipAllRequests.visibility = View.GONE
+ } else {
+ binding.devToolsHttpDebugFabSkipAllRequests.visibility = View.VISIBLE
+ }
+ }
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/list/ListItemDiffCallback.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/list/ListItemDiffCallback.kt
new file mode 100644
index 0000000..433c70e
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/list/ListItemDiffCallback.kt
@@ -0,0 +1,13 @@
+package com.trendyol.devtools.httpdebug.internal.ui.list
+
+import androidx.recyclerview.widget.DiffUtil
+import com.trendyol.devtools.httpdebug.internal.model.RequestResponse
+
+internal object ListItemDiffCallback : DiffUtil.ItemCallback() {
+
+ override fun areItemsTheSame(oldItem: RequestResponse, newItem: RequestResponse): Boolean =
+ oldItem == newItem
+
+ override fun areContentsTheSame(oldItem: RequestResponse, newItem: RequestResponse): Boolean =
+ oldItem.id == newItem.id
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/list/ListViewModel.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/list/ListViewModel.kt
new file mode 100644
index 0000000..1ece2f9
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/list/ListViewModel.kt
@@ -0,0 +1,35 @@
+package com.trendyol.devtools.httpdebug.internal.ui.list
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.trendyol.devtools.common.BaseViewModel
+import com.trendyol.devtools.httpdebug.internal.domain.GetActiveRequestsUseCase
+import com.trendyol.devtools.httpdebug.internal.domain.SkipRequestUseCase
+import com.trendyol.devtools.httpdebug.internal.model.RequestResponse
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
+
+internal class ListViewModel(
+ private val getActiveRequestsUseCase: GetActiveRequestsUseCase,
+ private val skipRequestUseCase: SkipRequestUseCase
+) : BaseViewModel() {
+
+ private val requestsLiveData = MutableLiveData>()
+
+ fun getRequestsLiveData(): LiveData> = requestsLiveData
+
+ fun getRequests() {
+ getActiveRequestsUseCase
+ .getActiveRequests()
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe { requestsLiveData.value = it }
+ .also(disposable::add)
+ }
+
+ fun skipRequest(id: String) {
+ //skipRequestUseCase.skipRequest(id)
+ }
+
+ fun skipAllRequests() {
+ skipRequestUseCase.skipAllRequests()
+ }
+}
diff --git a/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/list/RequestListAdapter.kt b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/list/RequestListAdapter.kt
new file mode 100644
index 0000000..464222b
--- /dev/null
+++ b/http-debug/src/main/java/com/trendyol/devtools/httpdebug/internal/ui/list/RequestListAdapter.kt
@@ -0,0 +1,38 @@
+package com.trendyol.devtools.httpdebug.internal.ui.list
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import com.trendyol.devtools.httpdebug.databinding.DevToolsHttpDebugItemListBinding
+import com.trendyol.devtools.httpdebug.internal.model.RequestResponse
+
+internal class RequestListAdapter(private val onRequestClicked: (String) -> Unit) :
+ ListAdapter(ListItemDiffCallback) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder =
+ ViewHolder(DevToolsHttpDebugItemListBinding.inflate(LayoutInflater.from(parent.context), parent, false))
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getItem(position))
+ }
+
+ inner class ViewHolder(private val binding: DevToolsHttpDebugItemListBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+
+ init {
+ binding.root.setOnClickListener {
+ onRequestClicked.invoke(getItem(adapterPosition).id)
+ }
+ }
+
+ fun bind(item: RequestResponse) {
+ with(binding) {
+ devToolsHttpDebugTextMethod.text = item.request.request.method
+ devToolsHttpDebugTextUrl.text = item.request.request.url.toString()
+ devToolsHttpDebugTextResponseCode.text = item.response.response?.code?.toString()
+ devToolsHttpDebugTextResponseCode.visibility = item.getResponseCodeVisibility()
+ }
+ }
+ }
+}
diff --git a/http-debug/src/main/res/drawable/ic_dev_tools_http_debug_double_arrow.xml b/http-debug/src/main/res/drawable/ic_dev_tools_http_debug_double_arrow.xml
new file mode 100644
index 0000000..edb1139
--- /dev/null
+++ b/http-debug/src/main/res/drawable/ic_dev_tools_http_debug_double_arrow.xml
@@ -0,0 +1,13 @@
+
+
+
+
diff --git a/http-debug/src/main/res/layout/dev_tools_http_debug_activity.xml b/http-debug/src/main/res/layout/dev_tools_http_debug_activity.xml
new file mode 100644
index 0000000..c53c83b
--- /dev/null
+++ b/http-debug/src/main/res/layout/dev_tools_http_debug_activity.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/http-debug/src/main/res/layout/dev_tools_http_debug_fragment_detail.xml b/http-debug/src/main/res/layout/dev_tools_http_debug_fragment_detail.xml
new file mode 100644
index 0000000..fb0ab60
--- /dev/null
+++ b/http-debug/src/main/res/layout/dev_tools_http_debug_fragment_detail.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/http-debug/src/main/res/layout/dev_tools_http_debug_fragment_list.xml b/http-debug/src/main/res/layout/dev_tools_http_debug_fragment_list.xml
new file mode 100644
index 0000000..423103f
--- /dev/null
+++ b/http-debug/src/main/res/layout/dev_tools_http_debug_fragment_list.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
diff --git a/http-debug/src/main/res/layout/dev_tools_http_debug_fragment_request_tab.xml b/http-debug/src/main/res/layout/dev_tools_http_debug_fragment_request_tab.xml
new file mode 100644
index 0000000..e658a6d
--- /dev/null
+++ b/http-debug/src/main/res/layout/dev_tools_http_debug_fragment_request_tab.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/http-debug/src/main/res/layout/dev_tools_http_debug_fragment_response_tab.xml b/http-debug/src/main/res/layout/dev_tools_http_debug_fragment_response_tab.xml
new file mode 100644
index 0000000..ba98a1e
--- /dev/null
+++ b/http-debug/src/main/res/layout/dev_tools_http_debug_fragment_response_tab.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/http-debug/src/main/res/layout/dev_tools_http_debug_item_list.xml b/http-debug/src/main/res/layout/dev_tools_http_debug_item_list.xml
new file mode 100644
index 0000000..95ebb02
--- /dev/null
+++ b/http-debug/src/main/res/layout/dev_tools_http_debug_item_list.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/http-debug/src/main/res/values/strings.xml b/http-debug/src/main/res/values/strings.xml
new file mode 100644
index 0000000..0835a0b
--- /dev/null
+++ b/http-debug/src/main/res/values/strings.xml
@@ -0,0 +1,7 @@
+
+
+ Skip
+ Request
+ Response
+ (Request body is either null or not presentable)
+
diff --git a/http-debug/src/main/res/values/styles.xml b/http-debug/src/main/res/values/styles.xml
new file mode 100644
index 0000000..fe032bf
--- /dev/null
+++ b/http-debug/src/main/res/values/styles.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/sample/build.gradle b/sample/build.gradle
index 4469f55..f7cbfd9 100644
--- a/sample/build.gradle
+++ b/sample/build.gradle
@@ -49,11 +49,12 @@ android {
dependencies {
debugImplementation project(':dev-tools')
+ debugImplementation project(':http-debug')
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
- implementation 'androidx.core:core-ktx:1.3.2'
- implementation 'androidx.appcompat:appcompat:1.2.0'
- implementation 'com.google.android.material:material:1.3.0'
+ implementation 'androidx.core:core-ktx:1.6.0'
+ implementation 'androidx.appcompat:appcompat:1.3.1'
+ implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
diff --git a/sample/src/main/java/com/trendyol/devtools/App.kt b/sample/src/main/java/com/trendyol/devtools/App.kt
index 6f7914f..5cd560b 100644
--- a/sample/src/main/java/com/trendyol/devtools/App.kt
+++ b/sample/src/main/java/com/trendyol/devtools/App.kt
@@ -8,6 +8,11 @@ class App : Application() {
override fun onCreate() {
super.onCreate()
TrendyolDevTools.init(this)
- TrendyolDevTools.addDebugAction(DebugActionItem("Toggle SSL Pinning"))
+ TrendyolDevTools.addDebugActionItems(
+ listOf(
+ DebugActionItem("Toggle SSL Pinning"),
+ DebugActionItem("Inspect")
+ )
+ )
}
}
diff --git a/sample/src/main/java/com/trendyol/devtools/ui/main/MainFragment.kt b/sample/src/main/java/com/trendyol/devtools/ui/main/MainFragment.kt
index 2f25c43..74a725a 100644
--- a/sample/src/main/java/com/trendyol/devtools/ui/main/MainFragment.kt
+++ b/sample/src/main/java/com/trendyol/devtools/ui/main/MainFragment.kt
@@ -20,8 +20,8 @@ class MainFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
MainFragmentBinding.inflate(inflater, container, false).also { binding = it }.root
- override fun onActivityCreated(savedInstanceState: Bundle?) {
- super.onActivityCreated(savedInstanceState)
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
binding.button.setOnClickListener {
diff --git a/settings.gradle b/settings.gradle
index 17b2a22..f67c8f5 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,3 +1,5 @@
rootProject.name = "dev-tools"
include ':sample'
include ':dev-tools'
+include ':http-debug'
+include ':common'