From 652bcf6ec230ca0403ada950879546db6305e80e Mon Sep 17 00:00:00 2001 From: srtvprateek Date: Fri, 21 Jul 2023 01:31:19 +0530 Subject: [PATCH 01/13] setup & cleanup --- .../main/java/com/pluto/plugin/DataModel.kt | 25 ++++------------ .../src/main/java/com/pluto/plugin/Plugin.kt | 10 +------ .../java/com/pluto/plugin/PluginEntity.kt | 8 +++++ .../main/java/com/pluto/plugin/PluginGroup.kt | 7 +++-- ...uto___ic_plugin_group_placeholder_icon.xml | 9 ++++++ .../java/com/demo/plugin/DemoNotification.kt | 30 +++++++++---------- .../main/java/com/demo/plugin/DemoPlugin.kt | 6 +--- .../src/main/java/com/demo/plugin/Session.kt | 5 ---- pluto/lib/src/main/java/com/pluto/Pluto.kt | 11 +++++-- .../java/com/pluto/plugin/PluginManager.kt | 15 +++++----- .../pluto/plugin/selector/PluginAdapter.kt | 3 ++ .../com/pluto/ui/selector/SelectorActivity.kt | 2 +- .../selector/options/PluginOptionAdapter.kt | 27 ----------------- .../options/PluginOptionItemHolder.kt | 29 ------------------ 14 files changed, 63 insertions(+), 124 deletions(-) create mode 100644 pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginEntity.kt create mode 100644 pluto-plugins/base/lib/src/main/res/drawable/pluto___ic_plugin_group_placeholder_icon.xml delete mode 100644 pluto-plugins/plugins/demo/lib/src/main/java/com/demo/plugin/Session.kt delete mode 100644 pluto/lib/src/main/java/com/pluto/ui/selector/options/PluginOptionAdapter.kt delete mode 100644 pluto/lib/src/main/java/com/pluto/ui/selector/options/PluginOptionItemHolder.kt diff --git a/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/DataModel.kt b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/DataModel.kt index c300fe8d..b77e14bc 100644 --- a/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/DataModel.kt +++ b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/DataModel.kt @@ -13,24 +13,9 @@ data class PluginConfiguration( val name: String, @DrawableRes val icon: Int = R.drawable.pluto___ic_plugin_placeholder_icon, val version: String -) : ListItem() { - val identifier = name.lowercase().replace(" ", "_", true) +) : ListItem() - override fun equals(other: Any?): Boolean { - return other is PluginConfiguration && identifier == other.identifier - } - - override fun hashCode(): Int { - return identifier.hashCode() - } -} - -data class PluginOption( - val id: String, - val label: String, - @DrawableRes val icon: Int = R.drawable.pluto___ic_plugin_placeholder_icon -) : ListItem() { - override fun equals(other: Any?): Boolean { - return other is PluginOption && id == other.id - } -} +data class PluginGroupConfiguration( + val name: String, + @DrawableRes val icon: Int = R.drawable.pluto___ic_plugin_group_placeholder_icon, +) : ListItem() diff --git a/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/Plugin.kt b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/Plugin.kt index 980bc955..5f68a013 100644 --- a/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/Plugin.kt +++ b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/Plugin.kt @@ -7,10 +7,9 @@ import androidx.annotation.Keep import androidx.fragment.app.Fragment import com.pluto.utilities.DebugLog import com.pluto.utilities.extensions.toast -import com.pluto.utilities.list.ListItem @Keep -abstract class Plugin(val devIdentifier: String) : ListItem() { +abstract class Plugin(val identifier: String) : PluginEntity(identifier) { val context: Context get() = returnContext() @@ -43,7 +42,6 @@ abstract class Plugin(val devIdentifier: String) : ListItem() { abstract fun getConfig(): PluginConfiguration abstract fun getView(): Fragment open fun getDeveloperDetails(): DeveloperDetails? = null - open fun shouldInstallPlugin(): Boolean = true /** * plugin lifecycle methods @@ -55,10 +53,4 @@ abstract class Plugin(val devIdentifier: String) : ListItem() { DebugLog.d("pluto_plugin", "view switched :: ${getConfig().name} : $savedInstanceState") context.toast("View switched to ${getConfig().name}") } - - @Deprecated("global level plugin options are no longer supported") - fun getOptions(): List = emptyList() - - override fun equals(other: Any?): Boolean = other is Plugin && devIdentifier == other.devIdentifier - override fun hashCode(): Int = devIdentifier.hashCode() } diff --git a/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginEntity.kt b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginEntity.kt new file mode 100644 index 00000000..520c4a9c --- /dev/null +++ b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginEntity.kt @@ -0,0 +1,8 @@ +package com.pluto.plugin + +import com.pluto.utilities.list.ListItem + +abstract class PluginEntity(private val identifier: String) : ListItem() { + override fun equals(other: Any?): Boolean = other is PluginEntity && identifier == other.identifier + override fun hashCode(): Int = identifier.hashCode() +} diff --git a/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginGroup.kt b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginGroup.kt index b1ba5ca5..cf29f574 100644 --- a/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginGroup.kt +++ b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginGroup.kt @@ -1,5 +1,8 @@ package com.pluto.plugin -import com.pluto.utilities.list.ListItem +abstract class PluginGroup(identifier: String) : PluginEntity(identifier) { -class PluginGroup : ListItem() + abstract fun getConfig(): PluginGroupConfiguration + + abstract fun getPlugins(): List +} diff --git a/pluto-plugins/base/lib/src/main/res/drawable/pluto___ic_plugin_group_placeholder_icon.xml b/pluto-plugins/base/lib/src/main/res/drawable/pluto___ic_plugin_group_placeholder_icon.xml new file mode 100644 index 00000000..90d3fab2 --- /dev/null +++ b/pluto-plugins/base/lib/src/main/res/drawable/pluto___ic_plugin_group_placeholder_icon.xml @@ -0,0 +1,9 @@ + + + diff --git a/pluto-plugins/plugins/demo/lib/src/main/java/com/demo/plugin/DemoNotification.kt b/pluto-plugins/plugins/demo/lib/src/main/java/com/demo/plugin/DemoNotification.kt index 43fa7dc0..a64af2ca 100644 --- a/pluto-plugins/plugins/demo/lib/src/main/java/com/demo/plugin/DemoNotification.kt +++ b/pluto-plugins/plugins/demo/lib/src/main/java/com/demo/plugin/DemoNotification.kt @@ -20,22 +20,20 @@ internal class DemoNotification(private val context: Context) { private val device = Device(context) fun add() { - Session.devIdentifier?.let { - createChannel() - val notification: Notification = NotificationCompat.Builder(context, CHANNEL_ID) - .setPriority(NotificationCompat.PRIORITY_DEFAULT) - .setContentTitle(context.getString(R.string.demo___notification_title, device.app.name)) - .setContentText(context.getString(R.string.demo___notification_subtitle)) - .setSmallIcon(R.drawable.demo___ic_plugin_icon) - .setContentIntent(PlutoInterface.notification.getPendingIntent(it)) - .setOngoing(false) - .setOnlyAlertOnce(true) - .setAutoCancel(true) - .setSilent(true) - .setSound(null) - .build() - manager?.notify(NOTIFICATION_ID, notification) - } + createChannel() + val notification: Notification = NotificationCompat.Builder(context, CHANNEL_ID) + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setContentTitle(context.getString(R.string.demo___notification_title, device.app.name)) + .setContentText(context.getString(R.string.demo___notification_subtitle)) + .setSmallIcon(R.drawable.demo___ic_plugin_icon) + .setContentIntent(PlutoInterface.notification.getPendingIntent(DemoPlugin.ID)) + .setOngoing(false) + .setOnlyAlertOnce(true) + .setAutoCancel(true) + .setSilent(true) + .setSound(null) + .build() + manager?.notify(NOTIFICATION_ID, notification) } fun remove() { diff --git a/pluto-plugins/plugins/demo/lib/src/main/java/com/demo/plugin/DemoPlugin.kt b/pluto-plugins/plugins/demo/lib/src/main/java/com/demo/plugin/DemoPlugin.kt index f5c101bd..286b4264 100644 --- a/pluto-plugins/plugins/demo/lib/src/main/java/com/demo/plugin/DemoPlugin.kt +++ b/pluto-plugins/plugins/demo/lib/src/main/java/com/demo/plugin/DemoPlugin.kt @@ -12,10 +12,6 @@ class DemoPlugin() : Plugin(ID) { @Deprecated("Use the default constructor DemoPlugin() instead.") constructor(identifier: String) : this() - init { - Session.devIdentifier = devIdentifier - } - override fun getConfig(): PluginConfiguration = PluginConfiguration( name = context.getString(R.string.demo___plugin_name), icon = R.drawable.demo___ic_plugin_icon, @@ -33,7 +29,7 @@ class DemoPlugin() : Plugin(ID) { override fun getView(): Fragment = DemoFragment() override fun onPluginInstalled() { - DebugLog.d("demo_plugin", "$devIdentifier installed") + DebugLog.d("demo_plugin", "$ID installed") } override fun onPluginDataCleared() { diff --git a/pluto-plugins/plugins/demo/lib/src/main/java/com/demo/plugin/Session.kt b/pluto-plugins/plugins/demo/lib/src/main/java/com/demo/plugin/Session.kt deleted file mode 100644 index e4d844e8..00000000 --- a/pluto-plugins/plugins/demo/lib/src/main/java/com/demo/plugin/Session.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.demo.plugin - -internal object Session { - var devIdentifier: String? = null -} diff --git a/pluto/lib/src/main/java/com/pluto/Pluto.kt b/pluto/lib/src/main/java/com/pluto/Pluto.kt index 4a9fc897..fc937994 100644 --- a/pluto/lib/src/main/java/com/pluto/Pluto.kt +++ b/pluto/lib/src/main/java/com/pluto/Pluto.kt @@ -10,6 +10,8 @@ import com.pluto.core.notch.Notch import com.pluto.core.notch.NotchStateCallback import com.pluto.core.notification.NotificationManager import com.pluto.plugin.Plugin +import com.pluto.plugin.PluginEntity +import com.pluto.plugin.PluginGroup import com.pluto.plugin.PluginManager import com.pluto.plugin.libinterface.NotificationInterface.Companion.BUNDLE_LABEL import com.pluto.plugin.libinterface.NotificationInterface.Companion.ID_LABEL @@ -38,7 +40,7 @@ object Pluto { internal lateinit var selectorStateCallback: SelectorStateCallback private lateinit var notchStateCallback: NotchStateCallback - private fun init(application: Application, plugins: LinkedHashSet) { + private fun init(application: Application, plugins: LinkedHashSet) { initialiseCallbacks() this.application = application appLifecycle = AppLifecycle(appStateCallback) @@ -98,13 +100,18 @@ object Pluto { class Installer(private val application: Application) { - private val plugins = linkedSetOf() + private val plugins = linkedSetOf() fun addPlugin(plugin: Plugin): Installer { plugins.add(plugin) return this } + fun addPluginGroup(pluginGroup: PluginGroup): Installer { + plugins.add(pluginGroup) + return this + } + fun install() { init(application, plugins) } diff --git a/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt b/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt index 643aa946..ddb59a52 100644 --- a/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt +++ b/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt @@ -4,7 +4,6 @@ import android.app.Application import com.pluto.plugin.libinterface.PlutoInterface import com.pluto.ui.container.PlutoActivity import com.pluto.ui.selector.SelectorActivity -import com.pluto.utilities.DebugLog internal class PluginManager(private val application: Application) { @@ -24,20 +23,20 @@ internal class PluginManager(private val application: Application) { ) } - fun install(plugins: LinkedHashSet) { + fun install(plugins: LinkedHashSet) { plugins.forEach { - if (it.shouldInstallPlugin()) { - it.install(application) - this.plugins.add(it) - } else { - DebugLog.e("pluto_plugin", "${it.getConfig().name} not installed (reason: condition mismatch).") + when (it) { + is Plugin -> { + it.install(application) + this.plugins.add(it) + } } } } fun get(identifier: String): Plugin? { return plugins.firstOrNull { - it.devIdentifier == identifier + it.identifier == identifier } } } diff --git a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginAdapter.kt b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginAdapter.kt index 1d6060d6..ae85c37f 100644 --- a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginAdapter.kt +++ b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginAdapter.kt @@ -2,6 +2,7 @@ package com.pluto.plugin.selector import android.view.ViewGroup import com.pluto.plugin.Plugin +import com.pluto.plugin.PluginGroup import com.pluto.utilities.list.BaseAdapter import com.pluto.utilities.list.DiffAwareHolder import com.pluto.utilities.list.ListItem @@ -10,6 +11,7 @@ internal class PluginAdapter(private val listener: OnActionListener) : BaseAdapt override fun getItemViewType(item: ListItem): Int? { return when (item) { is Plugin -> ITEM_TYPE_PLUGIN + is PluginGroup -> ITEM_TYPE_PLUGIN_GROUP else -> null } } @@ -23,5 +25,6 @@ internal class PluginAdapter(private val listener: OnActionListener) : BaseAdapt companion object { const val ITEM_TYPE_PLUGIN = 1000 + const val ITEM_TYPE_PLUGIN_GROUP = 1001 } } diff --git a/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt b/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt index 30ae2896..1f9f856b 100644 --- a/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt +++ b/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt @@ -114,7 +114,7 @@ class SelectorActivity : FragmentActivity() { when (data) { is Plugin -> when (action) { "click" -> { - Pluto.open(data.devIdentifier) + Pluto.open(data.identifier) finish() } "long_click" -> { diff --git a/pluto/lib/src/main/java/com/pluto/ui/selector/options/PluginOptionAdapter.kt b/pluto/lib/src/main/java/com/pluto/ui/selector/options/PluginOptionAdapter.kt deleted file mode 100644 index 418ce0d0..00000000 --- a/pluto/lib/src/main/java/com/pluto/ui/selector/options/PluginOptionAdapter.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.pluto.ui.selector.options - -import android.view.ViewGroup -import com.pluto.plugin.PluginOption -import com.pluto.utilities.list.BaseAdapter -import com.pluto.utilities.list.DiffAwareHolder -import com.pluto.utilities.list.ListItem - -internal class PluginOptionAdapter(private val listener: OnActionListener) : BaseAdapter() { - override fun getItemViewType(item: ListItem): Int? { - return when (item) { - is PluginOption -> ITEM_TYPE_PLUGIN_OPTION - else -> null - } - } - - override fun onViewHolderCreated(parent: ViewGroup, viewType: Int): DiffAwareHolder? { - return when (viewType) { - ITEM_TYPE_PLUGIN_OPTION -> PluginOptionItemHolder(parent, listener) - else -> null - } - } - - companion object { - const val ITEM_TYPE_PLUGIN_OPTION = 1000 - } -} diff --git a/pluto/lib/src/main/java/com/pluto/ui/selector/options/PluginOptionItemHolder.kt b/pluto/lib/src/main/java/com/pluto/ui/selector/options/PluginOptionItemHolder.kt deleted file mode 100644 index b66cec62..00000000 --- a/pluto/lib/src/main/java/com/pluto/ui/selector/options/PluginOptionItemHolder.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.pluto.ui.selector.options - -import android.view.ViewGroup -import com.pluto.R -import com.pluto.databinding.PlutoItemPluginOptionBinding -import com.pluto.plugin.PluginOption -import com.pluto.utilities.extensions.inflate -import com.pluto.utilities.list.DiffAwareAdapter -import com.pluto.utilities.list.DiffAwareHolder -import com.pluto.utilities.list.ListItem -import com.pluto.utilities.setOnDebounceClickListener - -internal class PluginOptionItemHolder(parent: ViewGroup, actionListener: DiffAwareAdapter.OnActionListener) : - DiffAwareHolder(parent.inflate(R.layout.pluto___item_plugin_option), actionListener) { - - private val binding = PlutoItemPluginOptionBinding.bind(itemView) - private val label = binding.label - private val icon = binding.icon - - override fun onBind(item: ListItem) { - if (item is PluginOption) { - icon.setImageResource(item.icon) - label.text = item.label - binding.root.setOnDebounceClickListener { - onAction("click") - } - } - } -} From e6047a585d2910925533a9e12ef7333e16e4ca19 Mon Sep 17 00:00:00 2001 From: srtvprateek Date: Fri, 21 Jul 2023 09:24:46 +0530 Subject: [PATCH 02/13] fixes --- pluto/lib/src/main/java/com/pluto/Pluto.kt | 11 ++---- .../java/com/pluto/plugin/PluginManager.kt | 38 +++++++++++++++---- .../java/com/pluto/plugin/PluginsViewModel.kt | 4 +- .../com/pluto/ui/selector/SelectorActivity.kt | 9 ++++- .../main/java/com/sampleapp/MainActivity.kt | 2 +- 5 files changed, 43 insertions(+), 21 deletions(-) diff --git a/pluto/lib/src/main/java/com/pluto/Pluto.kt b/pluto/lib/src/main/java/com/pluto/Pluto.kt index fc937994..7fba45a4 100644 --- a/pluto/lib/src/main/java/com/pluto/Pluto.kt +++ b/pluto/lib/src/main/java/com/pluto/Pluto.kt @@ -81,14 +81,9 @@ object Pluto { notch?.enable(state) } - fun clearAllLogs() { - pluginManager.installedPlugins.forEach { it.onPluginDataCleared() } - } - - fun clearLogs(plugin: Plugin) { - if (pluginManager.installedPlugins.contains(plugin)) { - plugin.onPluginDataCleared() - } + @JvmOverloads + fun clearLogs(identifier: String? = null) { + pluginManager.clearLogs(identifier) } private fun initialiseCallbacks() { diff --git a/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt b/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt index ddb59a52..f18b7dc6 100644 --- a/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt +++ b/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt @@ -7,19 +7,17 @@ import com.pluto.ui.selector.SelectorActivity internal class PluginManager(private val application: Application) { - private var plugins: LinkedHashSet = linkedSetOf() - internal val installedPlugins: List + private var plugins: LinkedHashSet = linkedSetOf() + internal val installedPlugins: List get() { - val list = arrayListOf() + val list = arrayListOf() list.addAll(plugins) return list } init { PlutoInterface.create( - application = application, - pluginActivityClass = PlutoActivity::class.java, - selectorActivityClass = SelectorActivity::class.java + application = application, pluginActivityClass = PlutoActivity::class.java, selectorActivityClass = SelectorActivity::class.java ) } @@ -30,13 +28,37 @@ internal class PluginManager(private val application: Application) { it.install(application) this.plugins.add(it) } + + is PluginGroup -> { + it.getPlugins().forEach { plugin -> + plugin.install(application) + } + this.plugins.add(it) + } } } } fun get(identifier: String): Plugin? { - return plugins.firstOrNull { - it.identifier == identifier + plugins.forEach { + when (it) { + is Plugin -> if (it.identifier == identifier) return it + is PluginGroup -> return it.getPlugins().firstOrNull { plugin -> plugin.identifier == identifier } + } + } + return null + } + + fun clearLogs(identifier: String? = null) { + identifier?.let { get(identifier)?.onPluginDataCleared() } ?: run { clearAllLogs() } + } + + private fun clearAllLogs() { + installedPlugins.forEach { + when (it) { + is Plugin -> it.onPluginDataCleared() + is PluginGroup -> it.getPlugins().forEach { plugin -> plugin.onPluginDataCleared() } + } } } } diff --git a/pluto/lib/src/main/java/com/pluto/plugin/PluginsViewModel.kt b/pluto/lib/src/main/java/com/pluto/plugin/PluginsViewModel.kt index 26184782..0ba2aecb 100644 --- a/pluto/lib/src/main/java/com/pluto/plugin/PluginsViewModel.kt +++ b/pluto/lib/src/main/java/com/pluto/plugin/PluginsViewModel.kt @@ -8,9 +8,9 @@ import com.pluto.Pluto internal class PluginsViewModel(application: Application) : AndroidViewModel(application) { - val plugins: LiveData> + val plugins: LiveData> get() = _plugins - private val _plugins = MutableLiveData>() + private val _plugins = MutableLiveData>() init { _plugins.postValue(Pluto.pluginManager.installedPlugins) diff --git a/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt b/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt index 1f9f856b..bc418faf 100644 --- a/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt +++ b/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt @@ -16,6 +16,8 @@ import com.pluto.R import com.pluto.core.applifecycle.AppStateCallback import com.pluto.databinding.PlutoActivityPluginSelectorBinding import com.pluto.plugin.Plugin +import com.pluto.plugin.PluginEntity +import com.pluto.plugin.PluginGroup import com.pluto.plugin.PluginsViewModel import com.pluto.plugin.selector.PluginAdapter import com.pluto.settings.SettingsFragment @@ -86,13 +88,16 @@ class SelectorActivity : FragmentActivity() { settingsViewModel.resetAll.observe(this) { Pluto.pluginManager.installedPlugins.forEach { - it.onPluginDataCleared() + when (it) { + is Plugin -> it.onPluginDataCleared() + is PluginGroup -> it.getPlugins().forEach { plugin -> plugin.onPluginDataCleared() } + } } Pluto.resetDataCallback.state.postValue(true) } } - private val pluginListObserver = Observer> { + private val pluginListObserver = Observer> { pluginAdapter.list = it if (it.isNullOrEmpty()) { binding.noPluginView.visibility = if (it.isNullOrEmpty()) VISIBLE else GONE diff --git a/sample/src/main/java/com/sampleapp/MainActivity.kt b/sample/src/main/java/com/sampleapp/MainActivity.kt index e226b942..1ef8ab60 100644 --- a/sample/src/main/java/com/sampleapp/MainActivity.kt +++ b/sample/src/main/java/com/sampleapp/MainActivity.kt @@ -42,7 +42,7 @@ class MainActivity : AppCompatActivity() { } binding.functionGroup.addView(chip) } - binding.clearLogsCta.setOnClickListener { Pluto.clearAllLogs() } + binding.clearLogsCta.setOnClickListener { Pluto.clearLogs() } binding.openPlutoCta.setOnClickListener { Pluto.open() } binding.showNotchCta.setOnClickListener { if (canDrawOverlays()) { From 0ab8710870e080f8ef5310667fe5007460ef573d Mon Sep 17 00:00:00 2001 From: srtvprateek Date: Fri, 21 Jul 2023 11:14:31 +0530 Subject: [PATCH 03/13] group item in selector --- .../pluto/plugin/selector/PluginAdapter.kt | 1 + .../plugin/selector/PluginGroupItemHolder.kt | 43 +++++++++++++++++++ .../com/pluto/ui/selector/SelectorActivity.kt | 2 + .../src/main/java/com/sampleapp/SampleApp.kt | 11 +++-- .../sampleapp/pluto/DataStorePluginGroup.kt | 25 +++++++++++ 5 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt create mode 100644 sample/src/main/java/com/sampleapp/pluto/DataStorePluginGroup.kt diff --git a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginAdapter.kt b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginAdapter.kt index ae85c37f..e0794d32 100644 --- a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginAdapter.kt +++ b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginAdapter.kt @@ -19,6 +19,7 @@ internal class PluginAdapter(private val listener: OnActionListener) : BaseAdapt override fun onViewHolderCreated(parent: ViewGroup, viewType: Int): DiffAwareHolder? { return when (viewType) { ITEM_TYPE_PLUGIN -> PluginItemHolder(parent, listener) + ITEM_TYPE_PLUGIN_GROUP -> PluginGroupItemHolder(parent, listener) else -> null } } diff --git a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt new file mode 100644 index 00000000..f2cedf3e --- /dev/null +++ b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt @@ -0,0 +1,43 @@ +package com.pluto.plugin.selector + +import android.view.ViewGroup +import android.view.animation.OvershootInterpolator +import com.pluto.R +import com.pluto.databinding.PlutoItemPluginBinding +import com.pluto.plugin.PluginGroup +import com.pluto.ui.selector.SelectorActivity.Companion.ANIMATION_DURATION +import com.pluto.ui.selector.loadAnimation +import com.pluto.utilities.extensions.inflate +import com.pluto.utilities.extensions.setListener +import com.pluto.utilities.list.DiffAwareAdapter +import com.pluto.utilities.list.DiffAwareHolder +import com.pluto.utilities.list.ListItem +import com.pluto.utilities.setOnDebounceClickListener + +internal class PluginGroupItemHolder(parent: ViewGroup, actionListener: DiffAwareAdapter.OnActionListener) : + DiffAwareHolder(parent.inflate(R.layout.pluto___item_plugin), actionListener) { + + private val binding = PlutoItemPluginBinding.bind(itemView) + private val name = binding.name + private val icon = binding.icon + + override fun onBind(item: ListItem) { + if (item is PluginGroup) { + icon.setImageResource(item.getConfig().icon) + name.text = item.getConfig().name + binding.root.setOnDebounceClickListener(haptic = true) { + val scale = context.loadAnimation(R.anim.pluto___click_bounce) + scale.duration = ANIMATION_DURATION + scale.interpolator = OvershootInterpolator() + scale.setListener { + onAnimationStart { + } + onAnimationEnd { + onAction("click") + } + } + it.startAnimation(scale) + } + } + } +} diff --git a/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt b/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt index bc418faf..eb60595f 100644 --- a/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt +++ b/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt @@ -28,6 +28,7 @@ import com.pluto.tool.selector.ToolAdapter import com.pluto.utilities.extensions.canDrawOverlays import com.pluto.utilities.extensions.color import com.pluto.utilities.extensions.openOverlaySettings +import com.pluto.utilities.extensions.toast import com.pluto.utilities.list.BaseAdapter import com.pluto.utilities.list.DiffAwareAdapter import com.pluto.utilities.list.DiffAwareHolder @@ -135,6 +136,7 @@ class SelectorActivity : FragmentActivity() { devDetailsFragment.show(supportFragmentManager, "devDetails") } } + is PluginGroup -> toast("group clicked ${data.getPlugins().size}") is PlutoTool -> { Pluto.toolManager.select(data.id) finish() diff --git a/sample/src/main/java/com/sampleapp/SampleApp.kt b/sample/src/main/java/com/sampleapp/SampleApp.kt index 041be222..be44665f 100644 --- a/sample/src/main/java/com/sampleapp/SampleApp.kt +++ b/sample/src/main/java/com/sampleapp/SampleApp.kt @@ -7,7 +7,6 @@ import android.os.StrictMode.VmPolicy import android.util.Log import com.demo.plugin.DemoPlugin import com.pluto.Pluto -import com.pluto.plugins.datastore.pref.PlutoDatastorePreferencesPlugin import com.pluto.plugins.datastore.pref.PlutoDatastoreWatcher import com.pluto.plugins.exceptions.PlutoExceptions import com.pluto.plugins.exceptions.PlutoExceptionsPlugin @@ -15,15 +14,14 @@ import com.pluto.plugins.layoutinspector.PlutoLayoutInspectorPlugin import com.pluto.plugins.logger.PlutoLoggerPlugin import com.pluto.plugins.logger.PlutoTimberTree import com.pluto.plugins.network.PlutoNetworkPlugin -import com.pluto.plugins.preferences.PlutoSharePreferencesPlugin import com.pluto.plugins.rooms.db.PlutoRoomsDBWatcher -import com.pluto.plugins.rooms.db.PlutoRoomsDatabasePlugin import com.sampleapp.functions.datastore.DemoDatastorePrefFragment.Companion.APP_STATE_PREF_NAME import com.sampleapp.functions.datastore.DemoDatastorePrefFragment.Companion.USER_STATE_PREF_NAME import com.sampleapp.functions.datastore.appStateDatastore import com.sampleapp.functions.datastore.userStateDatastore import com.sampleapp.functions.roomsdatabase.db.SampleDatabase import com.sampleapp.functions.roomsdatabase.db2.Sample2Database +import com.sampleapp.pluto.DataStorePluginGroup import kotlin.system.exitProcess import timber.log.Timber @@ -35,12 +33,13 @@ class SampleApp : Application() { Pluto.Installer(this) .addPlugin(DemoPlugin()) .addPlugin(PlutoExceptionsPlugin()) - .addPlugin(PlutoDatastorePreferencesPlugin()) +// .addPlugin(PlutoDatastorePreferencesPlugin()) .addPlugin(PlutoNetworkPlugin()) .addPlugin(PlutoLoggerPlugin()) - .addPlugin(PlutoSharePreferencesPlugin()) - .addPlugin(PlutoRoomsDatabasePlugin()) +// .addPlugin(PlutoSharePreferencesPlugin()) +// .addPlugin(PlutoRoomsDatabasePlugin()) .addPlugin(PlutoLayoutInspectorPlugin()) + .addPluginGroup(DataStorePluginGroup()) .install() Pluto.showNotch(true) diff --git a/sample/src/main/java/com/sampleapp/pluto/DataStorePluginGroup.kt b/sample/src/main/java/com/sampleapp/pluto/DataStorePluginGroup.kt new file mode 100644 index 00000000..fd253b1f --- /dev/null +++ b/sample/src/main/java/com/sampleapp/pluto/DataStorePluginGroup.kt @@ -0,0 +1,25 @@ +package com.sampleapp.pluto + +import com.pluto.plugin.Plugin +import com.pluto.plugin.PluginGroup +import com.pluto.plugin.PluginGroupConfiguration +import com.pluto.plugins.datastore.pref.PlutoDatastorePreferencesPlugin +import com.pluto.plugins.preferences.PlutoSharePreferencesPlugin +import com.pluto.plugins.rooms.db.PlutoRoomsDatabasePlugin + +class DataStorePluginGroup : PluginGroup(ID) { + + companion object { + const val ID = "datastore-group" + } + + override fun getConfig(): PluginGroupConfiguration = PluginGroupConfiguration( + name = "Datastore Group" + ) + + override fun getPlugins(): List = listOf( + PlutoSharePreferencesPlugin(), + PlutoDatastorePreferencesPlugin(), + PlutoRoomsDatabasePlugin() + ) +} From 012edc7821850b34b566604135047b9ca26509f9 Mon Sep 17 00:00:00 2001 From: srtvprateek Date: Thu, 10 Aug 2023 14:20:13 +0530 Subject: [PATCH 04/13] grouped plugin bottomsheet added --- .../java/com/pluto/plugin/PluginManager.kt | 2 + .../ui/selector/GroupSelectorFragment.kt | 77 +++++++++++++++++++ .../ui/selector/PluginsGroupViewModel.kt | 18 +++++ .../com/pluto/ui/selector/SelectorActivity.kt | 11 ++- .../pluto___fragment_group_selector.xml | 49 ++++++++++++ .../src/main/java/com/sampleapp/SampleApp.kt | 4 +- ...luginGroup.kt => DataSourcePluginGroup.kt} | 6 +- 7 files changed, 160 insertions(+), 7 deletions(-) create mode 100644 pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt create mode 100644 pluto/lib/src/main/java/com/pluto/ui/selector/PluginsGroupViewModel.kt create mode 100644 pluto/lib/src/main/res/layout/pluto___fragment_group_selector.xml rename sample/src/main/java/com/sampleapp/pluto/{DataStorePluginGroup.kt => DataSourcePluginGroup.kt} (83%) diff --git a/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt b/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt index f18b7dc6..0237178c 100644 --- a/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt +++ b/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt @@ -35,6 +35,8 @@ internal class PluginManager(private val application: Application) { } this.plugins.add(it) } + + else -> throw IllegalStateException("unknown PluginEntity type") } } } diff --git a/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt b/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt new file mode 100644 index 00000000..bc7a068d --- /dev/null +++ b/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt @@ -0,0 +1,77 @@ +package com.pluto.ui.selector + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.Observer +import androidx.recyclerview.widget.LinearLayoutManager +import com.google.android.material.bottomsheet.BottomSheetDialogFragment +import com.pluto.Pluto +import com.pluto.R +import com.pluto.databinding.PlutoFragmentGroupSelectorBinding +import com.pluto.plugin.Plugin +import com.pluto.plugin.PluginGroup +import com.pluto.plugin.selector.PluginAdapter +import com.pluto.utilities.extensions.toast +import com.pluto.utilities.list.BaseAdapter +import com.pluto.utilities.list.DiffAwareAdapter +import com.pluto.utilities.list.DiffAwareHolder +import com.pluto.utilities.list.ListItem +import com.pluto.utilities.viewBinding + +internal class GroupSelectorFragment : BottomSheetDialogFragment() { + + private val binding by viewBinding(PlutoFragmentGroupSelectorBinding::bind) + private val pluginsGroupViewModel by activityViewModels() + private val pluginAdapter: BaseAdapter by lazy { PluginAdapter(onActionListener) } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = + inflater.inflate(R.layout.pluto___fragment_group_selector, container, false) + + override fun getTheme(): Int = R.style.PlutoBottomSheetDialogTheme + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.list.apply { + adapter = pluginAdapter + layoutManager = LinearLayoutManager(context) + } + + pluginsGroupViewModel.current.removeObserver(pluginGroupObserver) + pluginsGroupViewModel.current.observe(this, pluginGroupObserver) + } + + private val pluginGroupObserver = Observer { + toast("group clicked ${it.getPlugins().size}") + binding.title.text = it.getConfig().name + pluginAdapter.list = it.getPlugins() + } + + private val onActionListener = object : DiffAwareAdapter.OnActionListener { + override fun onAction(action: String, data: ListItem, holder: DiffAwareHolder) { + when (data) { + is Plugin -> when (action) { + "click" -> { + Pluto.open(data.identifier) + activity?.finish() + } + "long_click" -> { + val devDetailsFragment = DevDetailsFragment() + devDetailsFragment.arguments = Bundle().apply { + putString("name", data.getConfig().name) + putInt("icon", data.getConfig().icon) + putString("version", data.getConfig().version) + putString("website", data.getDeveloperDetails()?.website) + putString("vcs", data.getDeveloperDetails()?.vcsLink) + putString("twitter", data.getDeveloperDetails()?.twitter) + } + devDetailsFragment.show(childFragmentManager, "devDetails") + } + } + } + } + } +} diff --git a/pluto/lib/src/main/java/com/pluto/ui/selector/PluginsGroupViewModel.kt b/pluto/lib/src/main/java/com/pluto/ui/selector/PluginsGroupViewModel.kt new file mode 100644 index 00000000..2e8a848a --- /dev/null +++ b/pluto/lib/src/main/java/com/pluto/ui/selector/PluginsGroupViewModel.kt @@ -0,0 +1,18 @@ +package com.pluto.ui.selector + +import android.app.Application +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.LiveData +import com.pluto.plugin.PluginGroup +import com.pluto.utilities.SingleLiveEvent + +internal class PluginsGroupViewModel(application: Application) : AndroidViewModel(application) { + + val current: LiveData + get() = _current + private val _current = SingleLiveEvent() + + fun set(group: PluginGroup) { + _current.postValue(group) + } +} diff --git a/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt b/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt index eb60595f..18d02923 100644 --- a/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt +++ b/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt @@ -28,7 +28,6 @@ import com.pluto.tool.selector.ToolAdapter import com.pluto.utilities.extensions.canDrawOverlays import com.pluto.utilities.extensions.color import com.pluto.utilities.extensions.openOverlaySettings -import com.pluto.utilities.extensions.toast import com.pluto.utilities.list.BaseAdapter import com.pluto.utilities.list.DiffAwareAdapter import com.pluto.utilities.list.DiffAwareHolder @@ -39,6 +38,7 @@ import com.pluto.utilities.spannable.setSpan class SelectorActivity : FragmentActivity() { private val pluginsViewModel by viewModels() + private val pluginsGroupViewModel by viewModels() private val pluginAdapter: BaseAdapter by lazy { PluginAdapter(onActionListener) } private val toolsViewModel by viewModels() private val toolAdapter: BaseAdapter by lazy { ToolAdapter(onActionListener) } @@ -123,6 +123,7 @@ class SelectorActivity : FragmentActivity() { Pluto.open(data.identifier) finish() } + "long_click" -> { val devDetailsFragment = DevDetailsFragment() devDetailsFragment.arguments = Bundle().apply { @@ -136,7 +137,13 @@ class SelectorActivity : FragmentActivity() { devDetailsFragment.show(supportFragmentManager, "devDetails") } } - is PluginGroup -> toast("group clicked ${data.getPlugins().size}") + + is PluginGroup -> { + pluginsGroupViewModel.set(data) + val groupSelectorFragment = GroupSelectorFragment() + groupSelectorFragment.show(supportFragmentManager, "groupSelector") + } + is PlutoTool -> { Pluto.toolManager.select(data.id) finish() diff --git a/pluto/lib/src/main/res/layout/pluto___fragment_group_selector.xml b/pluto/lib/src/main/res/layout/pluto___fragment_group_selector.xml new file mode 100644 index 00000000..b5e18c3b --- /dev/null +++ b/pluto/lib/src/main/res/layout/pluto___fragment_group_selector.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sample/src/main/java/com/sampleapp/SampleApp.kt b/sample/src/main/java/com/sampleapp/SampleApp.kt index be44665f..aa815df6 100644 --- a/sample/src/main/java/com/sampleapp/SampleApp.kt +++ b/sample/src/main/java/com/sampleapp/SampleApp.kt @@ -21,7 +21,7 @@ import com.sampleapp.functions.datastore.appStateDatastore import com.sampleapp.functions.datastore.userStateDatastore import com.sampleapp.functions.roomsdatabase.db.SampleDatabase import com.sampleapp.functions.roomsdatabase.db2.Sample2Database -import com.sampleapp.pluto.DataStorePluginGroup +import com.sampleapp.pluto.DataSourcePluginGroup import kotlin.system.exitProcess import timber.log.Timber @@ -39,7 +39,7 @@ class SampleApp : Application() { // .addPlugin(PlutoSharePreferencesPlugin()) // .addPlugin(PlutoRoomsDatabasePlugin()) .addPlugin(PlutoLayoutInspectorPlugin()) - .addPluginGroup(DataStorePluginGroup()) + .addPluginGroup(DataSourcePluginGroup()) .install() Pluto.showNotch(true) diff --git a/sample/src/main/java/com/sampleapp/pluto/DataStorePluginGroup.kt b/sample/src/main/java/com/sampleapp/pluto/DataSourcePluginGroup.kt similarity index 83% rename from sample/src/main/java/com/sampleapp/pluto/DataStorePluginGroup.kt rename to sample/src/main/java/com/sampleapp/pluto/DataSourcePluginGroup.kt index fd253b1f..9bee841f 100644 --- a/sample/src/main/java/com/sampleapp/pluto/DataStorePluginGroup.kt +++ b/sample/src/main/java/com/sampleapp/pluto/DataSourcePluginGroup.kt @@ -7,14 +7,14 @@ import com.pluto.plugins.datastore.pref.PlutoDatastorePreferencesPlugin import com.pluto.plugins.preferences.PlutoSharePreferencesPlugin import com.pluto.plugins.rooms.db.PlutoRoomsDatabasePlugin -class DataStorePluginGroup : PluginGroup(ID) { +class DataSourcePluginGroup : PluginGroup(ID) { companion object { - const val ID = "datastore-group" + const val ID = "datasource-group" } override fun getConfig(): PluginGroupConfiguration = PluginGroupConfiguration( - name = "Datastore Group" + name = "DataSource Group" ) override fun getPlugins(): List = listOf( From d1d1ed14455570797bd27627a39e19e7265cad81 Mon Sep 17 00:00:00 2001 From: srtvprateek Date: Sat, 12 Aug 2023 01:05:04 +0530 Subject: [PATCH 05/13] grouped plugin flow added --- .../src/main/java/com/pluto/plugin/Plugin.kt | 2 +- .../java/com/pluto/plugin/PluginEntity.kt | 3 +++ .../main/java/com/pluto/plugin/PluginGroup.kt | 20 +++++++++++++++++- .../java/com/pluto/plugin/PluginManager.kt | 21 ++++--------------- .../ui/selector/GroupSelectorFragment.kt | 4 +--- .../com/pluto/ui/selector/SelectorActivity.kt | 2 +- 6 files changed, 29 insertions(+), 23 deletions(-) diff --git a/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/Plugin.kt b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/Plugin.kt index 5f68a013..ae1492cb 100644 --- a/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/Plugin.kt +++ b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/Plugin.kt @@ -34,7 +34,7 @@ abstract class Plugin(val identifier: String) : PluginEntity(identifier) { var savedInstance: Bundle = Bundle() private set - fun install(application: Application) { + final override fun install(application: Application) { this._application = application onPluginInstalled() } diff --git a/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginEntity.kt b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginEntity.kt index 520c4a9c..2fbffd81 100644 --- a/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginEntity.kt +++ b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginEntity.kt @@ -1,8 +1,11 @@ package com.pluto.plugin +import android.app.Application import com.pluto.utilities.list.ListItem abstract class PluginEntity(private val identifier: String) : ListItem() { + + abstract fun install(application: Application) override fun equals(other: Any?): Boolean = other is PluginEntity && identifier == other.identifier override fun hashCode(): Int = identifier.hashCode() } diff --git a/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginGroup.kt b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginGroup.kt index cf29f574..4d73b232 100644 --- a/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginGroup.kt +++ b/pluto-plugins/base/lib/src/main/java/com/pluto/plugin/PluginGroup.kt @@ -1,8 +1,26 @@ package com.pluto.plugin +import android.app.Application + abstract class PluginGroup(identifier: String) : PluginEntity(identifier) { + private var plugins: LinkedHashSet = linkedSetOf() + + val installedPlugins: List + get() { + val list = arrayListOf() + list.addAll(plugins) + return list + } + abstract fun getConfig(): PluginGroupConfiguration - abstract fun getPlugins(): List + protected abstract fun getPlugins(): List + + final override fun install(application: Application) { + getPlugins().forEach { + it.install(application) + plugins.add(it) + } + } } diff --git a/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt b/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt index 0237178c..b405f7f3 100644 --- a/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt +++ b/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt @@ -23,21 +23,8 @@ internal class PluginManager(private val application: Application) { fun install(plugins: LinkedHashSet) { plugins.forEach { - when (it) { - is Plugin -> { - it.install(application) - this.plugins.add(it) - } - - is PluginGroup -> { - it.getPlugins().forEach { plugin -> - plugin.install(application) - } - this.plugins.add(it) - } - - else -> throw IllegalStateException("unknown PluginEntity type") - } + it.install(application) + this.plugins.add(it) } } @@ -45,7 +32,7 @@ internal class PluginManager(private val application: Application) { plugins.forEach { when (it) { is Plugin -> if (it.identifier == identifier) return it - is PluginGroup -> return it.getPlugins().firstOrNull { plugin -> plugin.identifier == identifier } + is PluginGroup -> return it.installedPlugins.firstOrNull { plugin -> plugin.identifier == identifier } } } return null @@ -59,7 +46,7 @@ internal class PluginManager(private val application: Application) { installedPlugins.forEach { when (it) { is Plugin -> it.onPluginDataCleared() - is PluginGroup -> it.getPlugins().forEach { plugin -> plugin.onPluginDataCleared() } + is PluginGroup -> it.installedPlugins.forEach { plugin -> plugin.onPluginDataCleared() } } } } diff --git a/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt b/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt index bc7a068d..6a128380 100644 --- a/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt +++ b/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt @@ -14,7 +14,6 @@ import com.pluto.databinding.PlutoFragmentGroupSelectorBinding import com.pluto.plugin.Plugin import com.pluto.plugin.PluginGroup import com.pluto.plugin.selector.PluginAdapter -import com.pluto.utilities.extensions.toast import com.pluto.utilities.list.BaseAdapter import com.pluto.utilities.list.DiffAwareAdapter import com.pluto.utilities.list.DiffAwareHolder @@ -45,9 +44,8 @@ internal class GroupSelectorFragment : BottomSheetDialogFragment() { } private val pluginGroupObserver = Observer { - toast("group clicked ${it.getPlugins().size}") binding.title.text = it.getConfig().name - pluginAdapter.list = it.getPlugins() + pluginAdapter.list = it.installedPlugins } private val onActionListener = object : DiffAwareAdapter.OnActionListener { diff --git a/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt b/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt index 18d02923..064a186e 100644 --- a/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt +++ b/pluto/lib/src/main/java/com/pluto/ui/selector/SelectorActivity.kt @@ -91,7 +91,7 @@ class SelectorActivity : FragmentActivity() { Pluto.pluginManager.installedPlugins.forEach { when (it) { is Plugin -> it.onPluginDataCleared() - is PluginGroup -> it.getPlugins().forEach { plugin -> plugin.onPluginDataCleared() } + is PluginGroup -> it.installedPlugins.forEach { plugin -> plugin.onPluginDataCleared() } } } Pluto.resetDataCallback.state.postValue(true) From be9e2e41c694612bd51d3ef31c7c97f24eb0eef3 Mon Sep 17 00:00:00 2001 From: srtvprateek Date: Sat, 12 Aug 2023 01:44:05 +0530 Subject: [PATCH 06/13] grouped plugin ui --- .../plugin/selector/PluginGroupAdapter.kt | 27 +++++++++++++ .../selector/PluginGroupChildItemHolder.kt | 30 +++++++++++++++ .../ui/selector/GroupSelectorFragment.kt | 4 +- .../pluto___fragment_group_selector.xml | 1 - .../pluto___item_plugin_group_child.xml | 38 +++++++++++++++++++ 5 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupAdapter.kt create mode 100644 pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupChildItemHolder.kt create mode 100644 pluto/lib/src/main/res/layout/pluto___item_plugin_group_child.xml diff --git a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupAdapter.kt b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupAdapter.kt new file mode 100644 index 00000000..955c6039 --- /dev/null +++ b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupAdapter.kt @@ -0,0 +1,27 @@ +package com.pluto.plugin.selector + +import android.view.ViewGroup +import com.pluto.plugin.Plugin +import com.pluto.utilities.list.BaseAdapter +import com.pluto.utilities.list.DiffAwareHolder +import com.pluto.utilities.list.ListItem + +internal class PluginGroupAdapter(private val listener: OnActionListener) : BaseAdapter() { + override fun getItemViewType(item: ListItem): Int? { + return when (item) { + is Plugin -> ITEM_TYPE_PLUGIN + else -> null + } + } + + override fun onViewHolderCreated(parent: ViewGroup, viewType: Int): DiffAwareHolder? { + return when (viewType) { + ITEM_TYPE_PLUGIN -> PluginGroupChildItemHolder(parent, listener) + else -> null + } + } + + companion object { + const val ITEM_TYPE_PLUGIN = 1000 + } +} diff --git a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupChildItemHolder.kt b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupChildItemHolder.kt new file mode 100644 index 00000000..dc6fc96e --- /dev/null +++ b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupChildItemHolder.kt @@ -0,0 +1,30 @@ +package com.pluto.plugin.selector + +import android.view.ViewGroup +import com.pluto.R +import com.pluto.databinding.PlutoItemPluginGroupChildBinding +import com.pluto.plugin.Plugin +import com.pluto.utilities.extensions.inflate +import com.pluto.utilities.list.DiffAwareAdapter +import com.pluto.utilities.list.DiffAwareHolder +import com.pluto.utilities.list.ListItem +import com.pluto.utilities.setOnDebounceClickListener + +internal class PluginGroupChildItemHolder(parent: ViewGroup, actionListener: DiffAwareAdapter.OnActionListener) : + DiffAwareHolder(parent.inflate(R.layout.pluto___item_plugin_group_child), actionListener) { + + private val binding = PlutoItemPluginGroupChildBinding.bind(itemView) + private val name = binding.name + private val icon = binding.icon + + override fun onBind(item: ListItem) { + if (item is Plugin) { + icon.setImageResource(item.getConfig().icon) + name.text = item.getConfig().name + + binding.root.setOnDebounceClickListener { + onAction("click") + } + } + } +} diff --git a/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt b/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt index 6a128380..44207626 100644 --- a/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt +++ b/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt @@ -13,7 +13,7 @@ import com.pluto.R import com.pluto.databinding.PlutoFragmentGroupSelectorBinding import com.pluto.plugin.Plugin import com.pluto.plugin.PluginGroup -import com.pluto.plugin.selector.PluginAdapter +import com.pluto.plugin.selector.PluginGroupAdapter import com.pluto.utilities.list.BaseAdapter import com.pluto.utilities.list.DiffAwareAdapter import com.pluto.utilities.list.DiffAwareHolder @@ -24,7 +24,7 @@ internal class GroupSelectorFragment : BottomSheetDialogFragment() { private val binding by viewBinding(PlutoFragmentGroupSelectorBinding::bind) private val pluginsGroupViewModel by activityViewModels() - private val pluginAdapter: BaseAdapter by lazy { PluginAdapter(onActionListener) } + private val pluginAdapter: BaseAdapter by lazy { PluginGroupAdapter(onActionListener) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View = inflater.inflate(R.layout.pluto___fragment_group_selector, container, false) diff --git a/pluto/lib/src/main/res/layout/pluto___fragment_group_selector.xml b/pluto/lib/src/main/res/layout/pluto___fragment_group_selector.xml index b5e18c3b..ec854b31 100644 --- a/pluto/lib/src/main/res/layout/pluto___fragment_group_selector.xml +++ b/pluto/lib/src/main/res/layout/pluto___fragment_group_selector.xml @@ -39,7 +39,6 @@ android:id="@+id/list" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginHorizontal="@dimen/pluto___margin_small" app:layout_constraintTop_toBottomOf="@+id/title" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" /> diff --git a/pluto/lib/src/main/res/layout/pluto___item_plugin_group_child.xml b/pluto/lib/src/main/res/layout/pluto___item_plugin_group_child.xml new file mode 100644 index 00000000..10ec1113 --- /dev/null +++ b/pluto/lib/src/main/res/layout/pluto___item_plugin_group_child.xml @@ -0,0 +1,38 @@ + + + + + + + + \ No newline at end of file From bdb770f35bbeed2d31b205e6a54691666e62b251 Mon Sep 17 00:00:00 2001 From: srtvprateek Date: Sat, 12 Aug 2023 01:47:05 +0530 Subject: [PATCH 07/13] ui fixes --- .../java/com/pluto/ui/selector/GroupSelectorFragment.kt | 7 +++++++ .../main/res/layout/pluto___item_plugin_group_child.xml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt b/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt index 44207626..20f711ad 100644 --- a/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt +++ b/pluto/lib/src/main/java/com/pluto/ui/selector/GroupSelectorFragment.kt @@ -14,7 +14,9 @@ import com.pluto.databinding.PlutoFragmentGroupSelectorBinding import com.pluto.plugin.Plugin import com.pluto.plugin.PluginGroup import com.pluto.plugin.selector.PluginGroupAdapter +import com.pluto.utilities.extensions.dp import com.pluto.utilities.list.BaseAdapter +import com.pluto.utilities.list.CustomItemDecorator import com.pluto.utilities.list.DiffAwareAdapter import com.pluto.utilities.list.DiffAwareHolder import com.pluto.utilities.list.ListItem @@ -37,6 +39,7 @@ internal class GroupSelectorFragment : BottomSheetDialogFragment() { binding.list.apply { adapter = pluginAdapter layoutManager = LinearLayoutManager(context) + addItemDecoration(CustomItemDecorator(context, DECORATOR_DIVIDER_PADDING)) } pluginsGroupViewModel.current.removeObserver(pluginGroupObserver) @@ -72,4 +75,8 @@ internal class GroupSelectorFragment : BottomSheetDialogFragment() { } } } + + private companion object { + val DECORATOR_DIVIDER_PADDING = 16f.dp.toInt() + } } diff --git a/pluto/lib/src/main/res/layout/pluto___item_plugin_group_child.xml b/pluto/lib/src/main/res/layout/pluto___item_plugin_group_child.xml index 10ec1113..05acec18 100644 --- a/pluto/lib/src/main/res/layout/pluto___item_plugin_group_child.xml +++ b/pluto/lib/src/main/res/layout/pluto___item_plugin_group_child.xml @@ -28,7 +28,7 @@ android:layout_marginStart="@dimen/pluto___margin_small" android:paddingVertical="@dimen/pluto___margin_mini" android:textColor="@color/pluto___text_dark_80" - android:textSize="@dimen/pluto___text_medium" + android:textSize="@dimen/pluto___text_xmedium" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/icon" From 7ba3872e4f0a9b523341548a5f41d57035ba2a8f Mon Sep 17 00:00:00 2001 From: srtvprateek Date: Sat, 12 Aug 2023 01:51:31 +0530 Subject: [PATCH 08/13] ui fixes --- .../plugin/selector/PluginGroupItemHolder.kt | 2 +- .../res/layout/pluto___item_plugin_group.xml | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 pluto/lib/src/main/res/layout/pluto___item_plugin_group.xml diff --git a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt index f2cedf3e..2c7ce35b 100644 --- a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt +++ b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt @@ -15,7 +15,7 @@ import com.pluto.utilities.list.ListItem import com.pluto.utilities.setOnDebounceClickListener internal class PluginGroupItemHolder(parent: ViewGroup, actionListener: DiffAwareAdapter.OnActionListener) : - DiffAwareHolder(parent.inflate(R.layout.pluto___item_plugin), actionListener) { + DiffAwareHolder(parent.inflate(R.layout.pluto___item_plugin_group), actionListener) { private val binding = PlutoItemPluginBinding.bind(itemView) private val name = binding.name diff --git a/pluto/lib/src/main/res/layout/pluto___item_plugin_group.xml b/pluto/lib/src/main/res/layout/pluto___item_plugin_group.xml new file mode 100644 index 00000000..402d4ddb --- /dev/null +++ b/pluto/lib/src/main/res/layout/pluto___item_plugin_group.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + \ No newline at end of file From e9bb47e7ad686b976ee3d0870ca3d58e2a0d0b39 Mon Sep 17 00:00:00 2001 From: srtvprateek Date: Sat, 12 Aug 2023 02:12:23 +0530 Subject: [PATCH 09/13] group icon fixes --- ...uto___ic_plugin_group_placeholder_icon.xml | 2 +- .../selector/PluginGroupChildItemHolder.kt | 4 +++ .../plugin/selector/PluginGroupItemHolder.kt | 24 ++++---------- .../res/layout/pluto___item_plugin_group.xml | 32 ++++++++++++++++--- 4 files changed, 39 insertions(+), 23 deletions(-) diff --git a/pluto-plugins/base/lib/src/main/res/drawable/pluto___ic_plugin_group_placeholder_icon.xml b/pluto-plugins/base/lib/src/main/res/drawable/pluto___ic_plugin_group_placeholder_icon.xml index 90d3fab2..0d228333 100644 --- a/pluto-plugins/base/lib/src/main/res/drawable/pluto___ic_plugin_group_placeholder_icon.xml +++ b/pluto-plugins/base/lib/src/main/res/drawable/pluto___ic_plugin_group_placeholder_icon.xml @@ -4,6 +4,6 @@ android:viewportWidth="24" android:viewportHeight="24"> diff --git a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupChildItemHolder.kt b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupChildItemHolder.kt index dc6fc96e..838fb4b2 100644 --- a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupChildItemHolder.kt +++ b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupChildItemHolder.kt @@ -25,6 +25,10 @@ internal class PluginGroupChildItemHolder(parent: ViewGroup, actionListener: Dif binding.root.setOnDebounceClickListener { onAction("click") } + binding.root.setOnLongClickListener { + onAction("long_click") + return@setOnLongClickListener true + } } } } diff --git a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt index 2c7ce35b..35882a12 100644 --- a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt +++ b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt @@ -1,14 +1,10 @@ package com.pluto.plugin.selector import android.view.ViewGroup -import android.view.animation.OvershootInterpolator import com.pluto.R -import com.pluto.databinding.PlutoItemPluginBinding +import com.pluto.databinding.PlutoItemPluginGroupBinding import com.pluto.plugin.PluginGroup -import com.pluto.ui.selector.SelectorActivity.Companion.ANIMATION_DURATION -import com.pluto.ui.selector.loadAnimation import com.pluto.utilities.extensions.inflate -import com.pluto.utilities.extensions.setListener import com.pluto.utilities.list.DiffAwareAdapter import com.pluto.utilities.list.DiffAwareHolder import com.pluto.utilities.list.ListItem @@ -17,26 +13,18 @@ import com.pluto.utilities.setOnDebounceClickListener internal class PluginGroupItemHolder(parent: ViewGroup, actionListener: DiffAwareAdapter.OnActionListener) : DiffAwareHolder(parent.inflate(R.layout.pluto___item_plugin_group), actionListener) { - private val binding = PlutoItemPluginBinding.bind(itemView) + private val binding = PlutoItemPluginGroupBinding.bind(itemView) private val name = binding.name private val icon = binding.icon + private val iconDummy = binding.iconDummy override fun onBind(item: ListItem) { if (item is PluginGroup) { icon.setImageResource(item.getConfig().icon) + iconDummy.setImageResource(item.getConfig().icon) name.text = item.getConfig().name - binding.root.setOnDebounceClickListener(haptic = true) { - val scale = context.loadAnimation(R.anim.pluto___click_bounce) - scale.duration = ANIMATION_DURATION - scale.interpolator = OvershootInterpolator() - scale.setListener { - onAnimationStart { - } - onAnimationEnd { - onAction("click") - } - } - it.startAnimation(scale) + binding.root.setOnDebounceClickListener { + onAction("click") } } } diff --git a/pluto/lib/src/main/res/layout/pluto___item_plugin_group.xml b/pluto/lib/src/main/res/layout/pluto___item_plugin_group.xml index 402d4ddb..806c40e3 100644 --- a/pluto/lib/src/main/res/layout/pluto___item_plugin_group.xml +++ b/pluto/lib/src/main/res/layout/pluto___item_plugin_group.xml @@ -7,6 +7,27 @@ android:background="?android:attr/selectableItemBackgroundBorderless" android:paddingVertical="@dimen/pluto___margin_medium"> + + + + + + + android:layout_margin="4dp" /> From f3efeb5ffbebfe805122da6c61ed9ae2688d3491 Mon Sep 17 00:00:00 2001 From: srtvprateek Date: Sat, 12 Aug 2023 11:27:30 +0530 Subject: [PATCH 10/13] refactor --- pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt b/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt index b405f7f3..cea916bc 100644 --- a/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt +++ b/pluto/lib/src/main/java/com/pluto/plugin/PluginManager.kt @@ -17,7 +17,9 @@ internal class PluginManager(private val application: Application) { init { PlutoInterface.create( - application = application, pluginActivityClass = PlutoActivity::class.java, selectorActivityClass = SelectorActivity::class.java + application = application, + pluginActivityClass = PlutoActivity::class.java, + selectorActivityClass = SelectorActivity::class.java ) } From d879e8dc91b489ed9d42b1eccceea46a03812352 Mon Sep 17 00:00:00 2001 From: Prateek Date: Sat, 12 Aug 2023 11:59:01 +0530 Subject: [PATCH 11/13] Update README.md --- README.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 264d4079..43a00967 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ # Android Pluto -Pluto - Open-sourced On-device debug framework for Android apps | Product Hunt [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.plutolib/pluto/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.plutolib/pluto) [![CLA assistant](https://cla-assistant.io/readme/badge/androidPluto/pluto)](https://cla-assistant.io/androidPluto/pluto) @@ -77,6 +76,34 @@ Now re-build and run your app, you will receive a notification from Pluto, use i
+## Grouping Plugins ***(Optional)*** +Pluto now allows to group similar plugins together to have better readability & categorization. +
+To create a group, we need to override PluginGroup & attach Plugins to it. + +```kotlin +class DataSourcePluginGroup : PluginGroup("datasource-group") { + + override fun getConfig() = PluginGroupConfiguration( + name = "DataSource Group" + ) + + override fun getPlugins() = listOf( + PlutoSharePreferencesPlugin(), + PlutoDatastorePreferencesPlugin(), + PlutoRoomsDatabasePlugin() + ) +} +``` + +Then add the group to Plugin installer. +```kotlin +Pluto.Installer(this) + .addPluginGroup(DataSourcePluginGroup()) + .install() +``` + +
## 📝  Contribution From f5a32dbc05f05c4e4294a73e0be04d06e5320b0a Mon Sep 17 00:00:00 2001 From: Prateek Date: Sat, 12 Aug 2023 12:01:17 +0530 Subject: [PATCH 12/13] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 43a00967..5022a910 100644 --- a/README.md +++ b/README.md @@ -76,10 +76,10 @@ Now re-build and run your app, you will receive a notification from Pluto, use i
-## Grouping Plugins ***(Optional)*** +## Grouping Plugins *(Optional)* Pluto now allows to group similar plugins together to have better readability & categorization.
-To create a group, we need to override PluginGroup & attach Plugins to it. +To create a group, we need to override PluginGroup & attach Plugins to it. *(We have taken the example of grouping datasource plugins together)* ```kotlin class DataSourcePluginGroup : PluginGroup("datasource-group") { From 25b1e62ecbcac08509f435d8eb93a6ddc64b4784 Mon Sep 17 00:00:00 2001 From: srtvprateek Date: Sat, 12 Aug 2023 12:40:36 +0530 Subject: [PATCH 13/13] ui fix --- .../plugin/selector/PluginGroupItemHolder.kt | 2 -- .../res/layout/pluto___item_plugin_group.xml | 28 +++++++++++++------ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt index 35882a12..3eb137d7 100644 --- a/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt +++ b/pluto/lib/src/main/java/com/pluto/plugin/selector/PluginGroupItemHolder.kt @@ -16,12 +16,10 @@ internal class PluginGroupItemHolder(parent: ViewGroup, actionListener: DiffAwar private val binding = PlutoItemPluginGroupBinding.bind(itemView) private val name = binding.name private val icon = binding.icon - private val iconDummy = binding.iconDummy override fun onBind(item: ListItem) { if (item is PluginGroup) { icon.setImageResource(item.getConfig().icon) - iconDummy.setImageResource(item.getConfig().icon) name.text = item.getConfig().name binding.root.setOnDebounceClickListener { onAction("click") diff --git a/pluto/lib/src/main/res/layout/pluto___item_plugin_group.xml b/pluto/lib/src/main/res/layout/pluto___item_plugin_group.xml index 806c40e3..f8588e9c 100644 --- a/pluto/lib/src/main/res/layout/pluto___item_plugin_group.xml +++ b/pluto/lib/src/main/res/layout/pluto___item_plugin_group.xml @@ -11,8 +11,8 @@ android:layout_width="0dp" android:layout_height="0dp" android:layout_marginStart="@dimen/pluto___margin_small" - android:background="@color/pluto___white_80" - android:backgroundTint="@color/pluto___white_80" + android:background="@color/pluto___white_60" + android:backgroundTint="@color/pluto___white_60" android:clipToPadding="true" app:cardCornerRadius="31dp" app:layout_constraintBottom_toBottomOf="@+id/iconCard" @@ -20,11 +20,21 @@ app:layout_constraintStart_toStartOf="@+id/iconCard" app:layout_constraintTop_toTopOf="@+id/iconCard"> - + + + @@ -37,7 +47,7 @@ android:clipToPadding="true" app:cardCornerRadius="31dp" app:layout_constraintHorizontal_bias="0.4" - app:cardElevation="@dimen/pluto___margin_mini" + app:cardElevation="@dimen/pluto___margin_xsmall" app:layout_constraintDimensionRatio="1:1" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -50,7 +60,7 @@ android:layout_width="32dp" android:layout_height="32dp" android:layout_gravity="center" - android:layout_margin="4dp" /> + android:layout_margin="5dp" />