Skip to content

ADFA-3598: Move jetpack compose preview into a plugin#1461

Merged
Daniel-ADFA merged 9 commits into
stagefrom
ADFA-3598
Jun 30, 2026
Merged

ADFA-3598: Move jetpack compose preview into a plugin#1461
Daniel-ADFA merged 9 commits into
stagefrom
ADFA-3598

Conversation

@Daniel-ADFA

Copy link
Copy Markdown
Contributor

No description provided.

itsaky and others added 5 commits June 16, 2026 19:25
Signed-off-by: Akash Yadav <itsaky01@gmail.com>
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
Add the host-side contract an external .cgp plugin needs to host the
Jetpack Compose preview feature independently of the app:

- IdeServices: add ModuleContext data class plus default-body
  IdeProjectService.getModuleContext(filePath) and
  IdeBuildService.executeTasks(vararg tasks) (binary-compatible
  additions via interface default methods)
- ModuleContextResolver: resolve a module's compile/runtime
  classpaths, resource APK and build state via IProjectManager /
  AndroidModule
- IdeProjectServiceImpl: implement getModuleContext over the resolver
- IdeBuildServiceImpl: bridge executeTasks to the host BuildService

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@Daniel-ADFA Daniel-ADFA requested a review from a team June 29, 2026 16:17
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough
  • Moved Jetpack Compose preview out of the app module and removed the standalone compose-preview module from the project.
  • Replaced the old compose-preview implementation with a plugin-driven approach for editor toolbar integration.
  • Added PluginToolbarActionItem to adapt plugin-provided toolbar actions into editor actions.
  • Extended plugin APIs so UI extensions can hide toolbar actions and toolbar actions can supply dynamic enabled/visible providers.
  • Added plugin-side module context access and build task execution support via new service APIs.
  • Updated the editor toolbar flow to respect plugin-hidden actions and visibility-aware toolbar items.
  • Removed compose-preview runtime, compiler, repository, parser, renderer, view model, and related UI/resources.

Risks / best-practice notes:

  • This is a large removal of preview infrastructure, so any existing Compose preview functionality is effectively gone unless fully replaced by the plugin path.
  • Several new APIs are additive with defaults for binary compatibility, but plugin authors may still need updates to adopt the new toolbar visibility and module context flows.
  • Path filtering and module context resolution changes affect plugin access control and could hide actions unexpectedly if IDs or permissions are misconfigured.

Walkthrough

Adds plugin toolbar action support, new plugin service APIs for module context and task execution, and removes compose-preview build wiring while limiting preview actions to XML layouts.

Changes

Plugin Toolbar Action System

Layer / File(s) Summary
Action and extension contracts
actions/.../ActionItem.kt, plugin-api/.../UIExtension.kt
Adds honorVisibility to ActionItem, getHiddenToolbarActionIds() to UIExtension, and optional enabled/visible providers on ToolbarAction.
Plugin toolbar action adapter
app/.../actions/PluginToolbarActionItem.kt
Adds an EditorActivityAction wrapper for plugin toolbar actions with id/order wiring, icon and label setup, provider-based visibility, show-as-action flags, tooltip metadata, and plugin execution.
Hidden toolbar ID aggregation
plugin-manager/.../ui/PluginUiActionManager.kt
Adds a singleton that unions hidden toolbar action IDs from enabled UI extensions and logs per-extension failures.
Toolbar registration and filtering
app/.../utils/EditorActivityActions.kt, app/.../activities/editor/EditorHandlerActivity.kt
Registers plugin toolbar actions, merges hidden IDs from build and UI managers, sorts toolbar actions, and skips honorVisibility actions when they are not visible.

Plugin Services API Extension

Layer / File(s) Summary
Module context and service APIs
plugin-api/.../services/IdeServices.kt
Adds ModuleContext, IdeProjectService.getModuleContext(), and IdeBuildService.executeTasks() with default implementations.
Module context resolution
plugin-manager/.../services/ModuleContextResolver.kt, plugin-manager/.../services/IdeProjectServiceImpl.kt
Adds module-context resolution for classpaths, runtime DEX, resource APKs, permission checks, and allowed paths.
Async build task execution
plugin-manager/.../services/IdeBuildServiceImpl.kt
Implements executeTasks() by resolving BuildService from Lookup and returning a boolean success result.

Compose Preview Removal and XML-only Preview

Layer / File(s) Summary
XML-only preview action
app/.../actions/etc/PreviewLayoutAction.kt
Restricts PreviewLayoutAction to XML layout preview, removes compose preview handling, and updates file-path trimming.
Compose preview build removal
app/build.gradle.kts, settings.gradle.kts
Removes the app module dependency on projects.composePreview and deletes :compose-preview from the Gradle settings include list.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • jatezzz
  • itsaky-adfa

🐇 The toolbar now hops with plugin cheer,
Hidden IDs vanish, visible ones appear.
XML previews stay, Compose hops away,
Module context and tasks join the fray.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.21% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive No pull request description was provided, so there is nothing substantive to assess. Add a brief description of the change and its purpose so reviewers can quickly understand the PR.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: moving Compose preview functionality into a plugin.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ADFA-3598

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (1)
profiler/build.gradle.kts (1)

8-10: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Wire profiler/proguard-rules.pro into the module config.
This file is currently unused; add consumerProguardFiles("proguard-rules.pro") if the library should publish keep rules, or remove it until needed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@profiler/build.gradle.kts` around lines 8 - 10, The profiler module currently
defines android { namespace = "${BuildConfig.PACKAGE_NAME}.profiler" } but does
not use profiler/proguard-rules.pro. Update the profiler module configuration in
build.gradle.kts to either wire in consumerProguardFiles("proguard-rules.pro")
if the library should ship keep rules, or remove the unused proguard file if it
is not needed. Use the android block and the profiler module’s Gradle config as
the place to make the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/main/java/com/itsaky/androidide/actions/etc/PreviewLayoutAction.kt`:
- Line 149: The preview base path in PreviewLayoutAction should not be derived
with substringBefore("layout"), since it can truncate earlier path segments in
directories that merely contain that word. Update the intent extra setup to
compute the prefix from the actual resource directory boundary in
PreviewLayoutAction (for example, using the layout folder segment or parent
directories) before passing Constants.EXTRA_KEY_FILE_PATH to EditorActivity.
- Around line 82-86: The probe in PreviewLayoutAction’s path parsing is catching
Throwable too broadly, which hides unexpected failures. Update the try/catch
around extractPathData(file) to catch only the specific parse exception it can
legitimately throw, and in that handler log or report the failure before calling
markInvisible(). Keep the fallback behavior in PreviewLayoutAction, but avoid
swallowing Errors or unrelated bugs.

In `@app/src/main/java/com/itsaky/androidide/utils/EditorActivityActions.kt`:
- Around line 190-194: The toolbar actions registered in EditorActivityActions
for PluginToolbarActionItem are not being rebuilt when a plugin is disabled, so
stale toolbar callbacks can remain active. Update
EditorHandlerActivity.tearDownDisabledPluginContributions() to clear and
re-register EDITOR_TOOLBAR actions from the currently enabled plugins, mirroring
the existing sidebar rebuild logic before invalidateOptionsMenu(). Use the
existing plugin action registration flow around plugin.getToolbarActions() and
registry.registerAction(...) so disabled plugins no longer leave behind toolbar
items.

In
`@plugin-api/src/main/kotlin/com/itsaky/androidide/plugins/extensions/UIExtension.kt`:
- Around line 141-155: ToolbarAction currently stores isEnabledProvider and
isVisibleProvider as mutable body properties, so data-class features like
copy(), equals(), and destructuring ignore them and copied actions lose the
dynamic callbacks. Move both provider callbacks into the primary constructor of
ToolbarAction and update any call sites/defaults so the data class includes them
in generated behavior while preserving the existing static isEnabled and
isVisible fallback logic.

In
`@plugin-manager/src/main/kotlin/com/itsaky/androidide/plugins/manager/services/IdeBuildServiceImpl.kt`:
- Around line 51-60: Gate the IdeBuildServiceImpl.executeTasks entry point
behind plugin-scoped authorization before forwarding to
BuildService.executeTasks. Add a permission check or a permission-aware wrapper
using the plugin identity available at the call site, and reject unauthorized
callers before any task execution is attempted. Keep the change localized to
executeTasks in IdeBuildServiceImpl and ensure only approved plugins can invoke
arbitrary Gradle tasks.

In
`@plugin-manager/src/main/kotlin/com/itsaky/androidide/plugins/manager/services/IdeProjectServiceImpl.kt`:
- Around line 84-94: getModuleContext() is missing the same host-path
authorization check used by getProjectByPath(), which allows probing disallowed
paths. Update IdeProjectServiceImpl.getModuleContext to validate the incoming
filePath with isPathAllowed() before calling ModuleContextResolver.resolve(),
and fail fast (for example with SecurityException) when the path is outside the
plugin’s allowed roots; keep the existing permission check and resolver flow
otherwise.

---

Nitpick comments:
In `@profiler/build.gradle.kts`:
- Around line 8-10: The profiler module currently defines android { namespace =
"${BuildConfig.PACKAGE_NAME}.profiler" } but does not use
profiler/proguard-rules.pro. Update the profiler module configuration in
build.gradle.kts to either wire in consumerProguardFiles("proguard-rules.pro")
if the library should ship keep rules, or remove the unused proguard file if it
is not needed. Use the android block and the profiler module’s Gradle config as
the place to make the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f80b052f-7faa-4500-ab06-8b0272dee1ce

📥 Commits

Reviewing files that changed from the base of the PR and between fc5b6f9 and 60b767e.

📒 Files selected for processing (45)
  • actions/src/main/java/com/itsaky/androidide/actions/ActionItem.kt
  • app/build.gradle.kts
  • app/src/main/java/com/itsaky/androidide/actions/PluginToolbarActionItem.kt
  • app/src/main/java/com/itsaky/androidide/actions/etc/PreviewLayoutAction.kt
  • app/src/main/java/com/itsaky/androidide/activities/editor/EditorHandlerActivity.kt
  • app/src/main/java/com/itsaky/androidide/utils/EditorActivityActions.kt
  • compose-preview/build.gradle.kts
  • compose-preview/src/main/AndroidManifest.xml
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/ComposePreviewActivity.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/ComposePreviewFragment.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/ComposePreviewViewModel.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/compiler/CompilerDaemon.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/compiler/ComposeClasspathManager.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/compiler/ComposeCompiler.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/compiler/ComposeDexCompiler.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/compiler/DexCache.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/data/repository/ComposePreviewRepository.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/data/repository/ComposePreviewRepositoryImpl.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/data/source/ProjectContextSource.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/domain/PreviewSourceParser.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/domain/model/ParsedPreviewSource.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/runtime/ComposableInvoker.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/runtime/ComposableRenderer.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/runtime/ComposeClassLoader.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/runtime/ComposeSignature.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/runtime/ProjectResourceContextFactory.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/ui/BoundedComposeView.kt
  • compose-preview/src/main/res/drawable/ic_view_grid.xml
  • compose-preview/src/main/res/drawable/ic_view_single.xml
  • compose-preview/src/main/res/layout/activity_compose_preview.xml
  • compose-preview/src/main/res/layout/fragment_compose_preview.xml
  • compose-preview/src/main/res/layout/item_preview_card.xml
  • compose-preview/src/main/res/menu/menu_compose_preview.xml
  • plugin-api/src/main/kotlin/com/itsaky/androidide/plugins/extensions/UIExtension.kt
  • plugin-api/src/main/kotlin/com/itsaky/androidide/plugins/services/IdeServices.kt
  • plugin-manager/src/main/kotlin/com/itsaky/androidide/plugins/manager/services/IdeBuildServiceImpl.kt
  • plugin-manager/src/main/kotlin/com/itsaky/androidide/plugins/manager/services/IdeProjectServiceImpl.kt
  • plugin-manager/src/main/kotlin/com/itsaky/androidide/plugins/manager/services/ModuleContextResolver.kt
  • plugin-manager/src/main/kotlin/com/itsaky/androidide/plugins/manager/ui/PluginUiActionManager.kt
  • profiler/.gitignore
  • profiler/build.gradle.kts
  • profiler/consumer-rules.pro
  • profiler/proguard-rules.pro
  • profiler/src/main/AndroidManifest.xml
  • settings.gradle.kts
💤 Files with no reviewable changes (28)
  • compose-preview/src/main/res/layout/fragment_compose_preview.xml
  • compose-preview/src/main/res/drawable/ic_view_grid.xml
  • compose-preview/src/main/res/menu/menu_compose_preview.xml
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/ComposePreviewActivity.kt
  • compose-preview/src/main/res/drawable/ic_view_single.xml
  • compose-preview/src/main/res/layout/item_preview_card.xml
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/runtime/ComposeSignature.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/data/source/ProjectContextSource.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/domain/model/ParsedPreviewSource.kt
  • compose-preview/src/main/res/layout/activity_compose_preview.xml
  • compose-preview/src/main/AndroidManifest.xml
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/compiler/DexCache.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/compiler/ComposeCompiler.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/runtime/ProjectResourceContextFactory.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/runtime/ComposeClassLoader.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/compiler/CompilerDaemon.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/ui/BoundedComposeView.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/domain/PreviewSourceParser.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/data/repository/ComposePreviewRepositoryImpl.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/data/repository/ComposePreviewRepository.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/ComposePreviewFragment.kt
  • compose-preview/build.gradle.kts
  • app/build.gradle.kts
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/compiler/ComposeDexCompiler.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/runtime/ComposableRenderer.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/compiler/ComposeClasspathManager.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/runtime/ComposableInvoker.kt
  • compose-preview/src/main/java/com/itsaky/androidide/compose/preview/ComposePreviewViewModel.kt

Comment thread app/src/main/java/com/itsaky/androidide/actions/etc/PreviewLayoutAction.kt Outdated
- PreviewLayoutAction: catch Exception (not Throwable) and log on resource-path
  parse failure; derive the layout base path from the last "layout/" segment
  instead of substringBefore("layout")
- EditorHandlerActivity: rebuild EDITOR_TOOLBAR plugin actions on plugin disable
  so stale PluginToolbarActionItem callbacks are cleared
- IdeProjectServiceImpl: path-validate getModuleContext via isPathAllowed()
- ToolbarAction: document why the provider callbacks stay body vars (ABI compat)

Deferred: permission-gating IdeBuildService.executeTasks needs a per-plugin
permission-aware wrapper + a new build permission (build service is a shared
singleton); to be done as a focused security change.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@plugin-manager/src/main/kotlin/com/itsaky/androidide/plugins/manager/services/IdeProjectServiceImpl.kt`:
- Around line 144-147: Keep the project-root lookups independent in
IdeProjectServiceImpl so a failure in getCurrentProject() does not prevent
getAllProjects() from being processed. Refactor the current runCatching block
around projectProvider.getCurrentProject() and projectProvider.getAllProjects()
so each call is handled separately, preserving roots collection even if one
source throws. Ensure the roots set is still populated from both sources using
the existing projectProvider and roots symbols.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f80c6ae3-bcb7-4eba-bc3f-0fb2a080a713

📥 Commits

Reviewing files that changed from the base of the PR and between 664062d and 9411f93.

📒 Files selected for processing (4)
  • app/src/main/java/com/itsaky/androidide/actions/etc/PreviewLayoutAction.kt
  • app/src/main/java/com/itsaky/androidide/activities/editor/EditorHandlerActivity.kt
  • plugin-api/src/main/kotlin/com/itsaky/androidide/plugins/extensions/UIExtension.kt
  • plugin-manager/src/main/kotlin/com/itsaky/androidide/plugins/manager/services/IdeProjectServiceImpl.kt
🚧 Files skipped from review as they are similar to previous changes (2)
  • plugin-api/src/main/kotlin/com/itsaky/androidide/plugins/extensions/UIExtension.kt
  • app/src/main/java/com/itsaky/androidide/actions/etc/PreviewLayoutAction.kt

@Daniel-ADFA Daniel-ADFA merged commit 6d1ce60 into stage Jun 30, 2026
2 checks passed
@Daniel-ADFA Daniel-ADFA deleted the ADFA-3598 branch June 30, 2026 10:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants