Skip to content

Commit 60a0493

Browse files
authored
chore(pluto): pluto documentation & testcases added (#353)
* chore(pluto): pluto documentation & testcases added * test cases
1 parent b354a1f commit 60a0493

Some content is hidden

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

50 files changed

+2140
-9
lines changed

gradle/libs.versions.toml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
[versions]
22

3+
testCore = "1.6.1"
4+
coreTesting = "2.2.0"
35
java = "1.8"
46

57
minSdk = "21"
8+
mockitoCore = "5.10.0"
9+
robolectric = "4.11.1"
10+
runner = "1.6.2"
611
targetSdk = "32"
712
compileSdk = "34"
813
buildTools = "34.0.0"
@@ -43,6 +48,8 @@ androidx-browser = { module = "androidx.browser:browser", version = "1.4.0" }
4348
androidx-cardview = { module = "androidx.cardview:cardview", version = "1.0.0" }
4449
androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version = "2.1.2" }
4550
androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidXCore" }
51+
androidx-core-testing = { module = "androidx.arch.core:core-testing", version.ref = "coreTesting" }
52+
androidx-test-core = { module = "androidx.test:core", version.ref = "testCore" }
4653
androidx-lifecycle-common = { module = "androidx.lifecycle:lifecycle-common-java8", version.ref = "androidXLifecycle" }
4754
androidx-lifecycle-livedata = { module = "androidx.lifecycle:lifecycle-livedata-ktx", version.ref = "androidXLifecycle" }
4855
androidx-lifecycle-viewmodel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidXLifecycle" }
@@ -51,6 +58,7 @@ androidx-navigation-fragment = { module = "androidx.navigation:navigation-fragme
5158
androidx-navigation-ui = { module = "androidx.navigation:navigation-ui", version.ref = "navigation" }
5259
androidx-preference = { module = "androidx.preference:preference-ktx", version = "1.2.0" }
5360
androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version = "1.2.1" }
61+
androidx-runner = { module = "androidx.test:runner", version.ref = "runner" }
5462
androidx-swiperefreshlayout = { module = "androidx.swiperefreshlayout:swiperefreshlayout", version = "1.1.0" }
5563

5664
datastore-preferences = { module = "androidx.datastore:datastore-preferences", version = "1.0.0" }
@@ -69,6 +77,7 @@ ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx
6977

7078
leakcanary-android = { module = "com.squareup.leakcanary:leakcanary-android", version = "2.7" }
7179

80+
mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockitoCore" }
7281
moshi = { module = "com.squareup.moshi:moshi", version.ref = "moshi" }
7382
moshi-codegen = { module = "com.squareup.moshi:moshi-kotlin-codegen", version.ref = "moshi" }
7483

@@ -78,6 +87,7 @@ okio = { module = "com.squareup.okio:okio", version = "2.10.0" }
7887

7988
retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
8089
retrofit-converter-moshi = { module = "com.squareup.retrofit2:converter-moshi", version.ref = "retrofit" }
90+
robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" }
8191
room = { module = "androidx.room:room-ktx", version.ref = "room" }
8292
room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
8393

pluto-plugins/base/lib/src/main/java/com/pluto/plugin/DataModel.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,47 @@ package com.pluto.plugin
22

33
import androidx.annotation.DrawableRes
44

5+
/**
6+
* Data class containing details about a plugin's developer.
7+
*
8+
* This class is used to provide information about the developer of a plugin,
9+
* which can be displayed in the plugin's details screen.
10+
*
11+
* @property vcsLink Optional link to the version control system repository
12+
* @property website Optional link to the developer's website
13+
* @property twitter Optional link to the developer's Twitter profile
14+
*/
515
data class DeveloperDetails(
616
val vcsLink: String? = null,
717
val website: String? = null,
818
val twitter: String? = null
919
)
1020

21+
/**
22+
* Data class containing configuration for a plugin.
23+
*
24+
* This class defines the visual and metadata properties of a plugin,
25+
* such as its name, icon, and version.
26+
*
27+
* @property name The display name of the plugin
28+
* @property icon The resource ID of the plugin's icon
29+
* @property version The version string of the plugin
30+
*/
1131
data class PluginConfiguration(
1232
val name: String,
1333
@DrawableRes val icon: Int = R.drawable.pluto___ic_plugin_placeholder_icon,
1434
val version: String
1535
)
1636

37+
/**
38+
* Data class containing configuration for a plugin group.
39+
*
40+
* This class defines the visual properties of a plugin group,
41+
* such as its name and icon.
42+
*
43+
* @property name The display name of the plugin group
44+
* @property icon The resource ID of the plugin group's icon
45+
*/
1746
data class PluginGroupConfiguration(
1847
val name: String,
1948
@DrawableRes val icon: Int = R.drawable.pluto___ic_plugin_group_placeholder_icon,

pluto-plugins/base/lib/src/main/java/com/pluto/plugin/Plugin.kt

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,47 +8,161 @@ import android.widget.Toast.LENGTH_SHORT
88
import androidx.annotation.Keep
99
import androidx.fragment.app.Fragment
1010

11+
/**
12+
* Base class for all Pluto plugins.
13+
*
14+
* This abstract class provides the foundation for creating Pluto debugging plugins.
15+
* It handles plugin lifecycle, configuration, and UI presentation.
16+
*
17+
* To create a new plugin, extend this class and implement the required abstract methods.
18+
*
19+
* Example:
20+
* ```
21+
* class NetworkPlugin : Plugin("network") {
22+
* override fun getConfig() = PluginConfiguration(
23+
* name = "Network",
24+
* icon = R.drawable.ic_network,
25+
* version = "1.0.0"
26+
* )
27+
*
28+
* override fun getView() = NetworkFragment()
29+
*
30+
* override fun onPluginInstalled() {
31+
* // Initialize plugin resources
32+
* }
33+
*
34+
* override fun onPluginDataCleared() {
35+
* // Clear plugin data
36+
* }
37+
* }
38+
* ```
39+
*
40+
* @property identifier A unique string identifier for the plugin
41+
*/
1142
@Keep
1243
abstract class Plugin(val identifier: String) : PluginEntity(identifier) {
1344

45+
/**
46+
* The application context.
47+
*
48+
* This property provides access to the application context for the plugin.
49+
* It throws an IllegalStateException if accessed before the plugin is installed.
50+
*/
1451
val context: Context
1552
get() = returnContext()
53+
54+
/**
55+
* The application instance.
56+
*
57+
* This property provides access to the application instance for the plugin.
58+
* It throws an IllegalStateException if accessed before the plugin is installed.
59+
*/
1660
val application: Application
1761
get() = returnApplication()
1862

63+
/** The internal application instance, set during installation */
1964
private var _application: Application? = null
65+
66+
/**
67+
* Returns the application context.
68+
*
69+
* @throws IllegalStateException if the plugin is not installed
70+
* @return The application context
71+
*/
2072
private fun returnContext(): Context {
2173
_application?.let {
2274
return it.applicationContext
2375
}
2476
throw IllegalStateException("${this.javaClass.name} plugin is not installed yet.")
2577
}
2678

79+
/**
80+
* Returns the application instance.
81+
*
82+
* @throws IllegalStateException if the plugin is not installed
83+
* @return The application instance
84+
*/
2785
private fun returnApplication(): Application {
2886
_application?.let {
2987
return it
3088
}
3189
throw IllegalStateException("${this.javaClass.name} plugin is not installed yet.")
3290
}
3391

92+
/**
93+
* Bundle for saving instance state.
94+
*
95+
* This bundle can be used to save and restore the plugin's state.
96+
*/
3497
var savedInstance: Bundle = Bundle()
3598
private set
3699

100+
/**
101+
* Installs the plugin with the provided application instance.
102+
*
103+
* This method is final and cannot be overridden. It sets the application
104+
* instance and calls onPluginInstalled().
105+
*
106+
* @param application The application instance to use for installation
107+
*/
37108
final override fun install(application: Application) {
38109
this._application = application
39110
onPluginInstalled()
40111
}
41112

113+
/**
114+
* Returns the plugin configuration.
115+
*
116+
* This method should provide a PluginConfiguration object that defines
117+
* the plugin's name, icon, and version.
118+
*
119+
* @return The plugin configuration
120+
*/
42121
abstract fun getConfig(): PluginConfiguration
122+
123+
/**
124+
* Returns the plugin's UI view.
125+
*
126+
* This method should provide a Fragment that implements the plugin's UI.
127+
*
128+
* @return The plugin's UI fragment
129+
*/
43130
abstract fun getView(): Fragment
131+
132+
/**
133+
* Returns the plugin developer's details.
134+
*
135+
* This method can be overridden to provide information about the plugin's
136+
* developer, such as VCS link, website, and Twitter handle.
137+
*
138+
* @return The developer details, or null if not provided
139+
*/
44140
open fun getDeveloperDetails(): DeveloperDetails? = null
45141

46142
/**
47-
* plugin lifecycle methods
143+
* Called when the plugin is installed.
144+
*
145+
* This method is called during the plugin installation process.
146+
* It should be used to initialize any resources needed by the plugin.
48147
*/
49148
abstract fun onPluginInstalled()
149+
150+
/**
151+
* Called when the plugin's data should be cleared.
152+
*
153+
* This method is called when the user requests to clear the plugin's data.
154+
* It should be used to clear any cached data or logs.
155+
*/
50156
abstract fun onPluginDataCleared()
51157

158+
/**
159+
* Called when the plugin's view is created.
160+
*
161+
* This method is called when the plugin's UI is created.
162+
* It shows a toast message indicating that the view has switched to this plugin.
163+
*
164+
* @param savedInstanceState The saved instance state bundle
165+
*/
52166
@SuppressWarnings("UnusedPrivateMember")
53167
fun onPluginViewCreated(savedInstanceState: Bundle?) {
54168
Toast.makeText(context, "View switched to ${getConfig().name}", LENGTH_SHORT).show()

pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginEntity.kt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,41 @@ package com.pluto.plugin
22

33
import android.app.Application
44

5+
/**
6+
* Base class for all Pluto plugin entities.
7+
*
8+
* This abstract class serves as the foundation for both individual plugins and plugin groups.
9+
* It provides a common interface for installation and identity management.
10+
*
11+
* @property identifier A unique string identifier for the plugin entity
12+
*/
513
abstract class PluginEntity(private val identifier: String) {
614

15+
/**
16+
* Installs the plugin entity with the provided application instance.
17+
*
18+
* This method is called during Pluto initialization to set up the plugin.
19+
*
20+
* @param application The application instance to use for installation
21+
*/
722
abstract fun install(application: Application)
23+
24+
/**
25+
* Compares this plugin entity with another object for equality.
26+
*
27+
* Plugin entities are considered equal if they have the same identifier.
28+
*
29+
* @param other The object to compare with
30+
* @return True if the objects are equal, false otherwise
31+
*/
832
override fun equals(other: Any?): Boolean = other is PluginEntity && identifier == other.identifier
33+
34+
/**
35+
* Returns a hash code value for this plugin entity.
36+
*
37+
* The hash code is based on the identifier to ensure consistency with equals.
38+
*
39+
* @return The hash code value
40+
*/
941
override fun hashCode(): Int = identifier.hashCode()
1042
}

pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginGroup.kt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,77 @@ package com.pluto.plugin
22

33
import android.app.Application
44

5+
/**
6+
* Base class for grouping related Pluto plugins.
7+
*
8+
* This abstract class allows multiple plugins to be grouped together under a
9+
* common identifier. Plugin groups are useful for organizing related plugins,
10+
* such as database inspection tools or network monitoring utilities.
11+
*
12+
* To create a new plugin group, extend this class and implement the required
13+
* abstract methods.
14+
*
15+
* Example:
16+
* ```
17+
* class DatabasePluginGroup : PluginGroup("database") {
18+
* override fun getConfig() = PluginGroupConfiguration(
19+
* name = "Database Tools"
20+
* )
21+
*
22+
* override fun getPlugins() = listOf(
23+
* RoomDatabasePlugin(),
24+
* SharedPreferencesPlugin()
25+
* )
26+
* }
27+
* ```
28+
*
29+
* @param identifier A unique string identifier for the plugin group
30+
*/
531
abstract class PluginGroup(identifier: String) : PluginEntity(identifier) {
632

33+
/** Set of installed plugins in this group */
734
private var plugins: LinkedHashSet<Plugin> = linkedSetOf()
835

36+
/**
37+
* List of all installed plugins in this group.
38+
*
39+
* This property returns a copy of the internal plugins set as a list,
40+
* ensuring that the original set cannot be modified externally.
41+
*/
942
val installedPlugins: List<Plugin>
1043
get() {
1144
val list = arrayListOf<Plugin>()
1245
list.addAll(plugins)
1346
return list
1447
}
1548

49+
/**
50+
* Returns the plugin group configuration.
51+
*
52+
* This method should provide a PluginGroupConfiguration object that defines
53+
* the group's name and icon.
54+
*
55+
* @return The plugin group configuration
56+
*/
1657
abstract fun getConfig(): PluginGroupConfiguration
1758

59+
/**
60+
* Returns the list of plugins in this group.
61+
*
62+
* This method should provide a list of all plugins that belong to this group.
63+
*
64+
* @return The list of plugins in this group
65+
*/
1866
protected abstract fun getPlugins(): List<Plugin>
1967

68+
/**
69+
* Installs all plugins in this group with the provided application instance.
70+
*
71+
* This method is final and cannot be overridden. It installs each plugin
72+
* in the group and adds it to the internal registry of plugins.
73+
*
74+
* @param application The application instance to use for installation
75+
*/
2076
final override fun install(application: Application) {
2177
getPlugins().forEach {
2278
it.install(application)

pluto/lib/build.gradle.kts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,12 @@ dependencies {
107107

108108
implementation(libs.moshi)
109109
ksp(libs.moshi.codegen)
110+
111+
// Test dependencies
112+
testImplementation(libs.junit)
113+
testImplementation(libs.robolectric)
114+
testImplementation(libs.mockito.core)
115+
testImplementation(libs.androidx.core.testing)
116+
testImplementation(libs.androidx.test.core)
117+
testImplementation(libs.androidx.runner)
110118
}

0 commit comments

Comments
 (0)