Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for CustomPreviewAnnotations in Showkase 🚿 🌈 #303

Merged

Conversation

oas004
Copy link
Contributor

@oas004 oas004 commented Feb 12, 2023

This was moved from #263 to avoid a lot of the heat after rebasing. Also fixed some of the stuff for the compiler args so that it works for KAPT as well.

Add support for CustomMultiPreviewAnnotations in Showkase.

This is the third PR in a series to add support for Custom MultiPreview Annotations. Referencing as a followup on #259 and #255.

By completing this should solve #233

resolves #233

What do I mean by Custom Preview Annotations?

This is an annotation in the form

@Preview(name = "Custom Preview One First", group = "Custom Previews")
@Preview(name = "Custom Preview One Second", group = "Custom Previews")
annotation class CustomPreview1
@Preview(name = "Custom Preview One First", group = "Custom Previews")
annotation class CustomPreview2

this can be used to annotate a composable function like you would do any other preview function in Compose like this:

@CustomPreview1
@Composable
fun CustomAnnotationPreview() {
}

This can also be combined like this:

@Preview(name = "Custom Preview One First", group = "Custom Previews")
@Preview(name = "Custom Preview One Second", group = "Custom Previews")
annotation class CustomPreviewOne


@Preview(name = "Custom Preview Two First", group = "Custom Previews")
annotation class CustomPreviewTwo

@CustomPreviewOne
@CustomPreviewTwo
@Composable
fun CustomAnnotationPreviewCombined() {
}

They should be able to have the custom annotations and the use of them in different modules in a project.

For more information, please see docs on tooling in compose here

Goal

The goal is to add support for this in Showkase. We would like showkase to act like the tooling in Android Studio does. That means that when Android Studio Preview would have generated a Preview, showkase should also generate a ShowkaseMetadata function.

KAPT vs KSP

Because of https://youtrack.jetbrains.com/issue/KT-49682/Support-JVM-IR-in-KAPT-stub-generation KAPT does not quite support repeatable annotations from Kotlin. This means that if you have an annotation class like:

@Preview(name = "Shape 100 by 100", group = "Shapes", widthDp = 100, heightDp = 100)
@Preview(name = "Shape 150 by 150", group = "Shapes", widthDp = 150, heightDp = 150)
annotation class CustomShape

This will be skipped by KAPT, but KSP will pick it up. However, if you have an annotation like:

@Preview(name = "Shape 100 by 100", group = "Shapes", widthDp = 100, heightDp = 100)
annotation class CustomShape

It will be picked up by both KSP and KAPT.

Important for KAPT users

You will need to provide a compiler arg in you module for the custom preview annotations that you are using and expecting to be picked up by Showkase. This can be done with the following code:

kapt  {
        arguments {
            arg("multiPreviewType","com.airbnb.android.submodule.showkasesample.LocalePreview")
        }
    }

It is important to remember to use the whole qualified name of the annotation, and not just the name.

Testing

Sample App

In the sample app I have introduced CustomShape from the same module

@Preview(name = "Shape 100 by 100", group = "Shapes", widthDp = 100, heightDp = 100)
@Preview(name = "Shape 150 by 150", group = "Shapes", widthDp = 150, heightDp = 150)
annotation class CustomShape

And FontPreview from the same module

@Preview(name = "Normal font size", group = "FontPreview", fontScale = 1f)
@Preview(name = "High font size", group = "FontPreview", fontScale = 1.5f)
@Preview(name = "Super High font size", group = "FontPreview", fontScale = 2f)
annotation class FontPreview

You can check this in the sample app if you build it with KSP.

Browser Test

In the browser tests I have introduced CustomTextPreview

@Preview(
    name = "Custom Text Dark",
    group = "Custom Text",
    uiMode = Configuration.UI_MODE_NIGHT_YES,
)
annotation class CustomTextPreview

There was already a composable to verify compilation from a pervious PR, so used that as well. Since the CustomTextPreview only had one Preview annotation, this was tested to be visible with KAPT as well.

I have done the same with the submodule in the browser test. However, here I introduced CustomSizePreview and CustomFontSizePreview and verified that it works with both KAPT and KSP.


@Preview(name = "CustomSize 100 * 100", widthDp = 100, heightDp = 100, group = "CustomSubmodulePreview")
@Preview(name = "CustomSize 200 * 200", widthDp = 200, heightDp = 200, group = "CustomSubmodulePreview")
annotation class CustomSizePreview

@Preview(name = "Custom Font Size 1.2f", fontScale = 1.2f, group = "Custom Size Submodule")
annotation class CustomFontSizePreview

Processor Test

In the processor tests, I have made tests that make sure all the correct metadata objects are created and that we are creating the files to store the custom annotations that the processor has registered. You can check these tests in showcase-processor-testing module.

  • Make custom multi preview annotations work for annotations that are in the same module as the showkase preview.
  • Make custom multi preview annotations work for annotations that are in a different module as the showkase preview and is imported into the file that has the showkase preview.
  • Add processor tests for the different cases.
  • Add Browser tests for the singular module case.
  • Add Browser tests for the multi module case.
  • Add processor test for combining custom annotations.
  • Add processor tests for KAPT case and KSP case.

@oas004 oas004 force-pushed the feature/custom-preview-annotation-support branch from be215b0 to 5d4db05 Compare February 13, 2023 17:33
@anhanh11001
Copy link

Thanks a lot for this work @oas004 🙏 🙏 🎆 🍾

This was done because we figured out that the metadata generation strategy works and this will give a better result to the enduser.
@oas004 oas004 force-pushed the feature/custom-preview-annotation-support branch from 312680c to 720166d Compare February 20, 2023 15:44
@oas004 oas004 force-pushed the feature/custom-preview-annotation-support branch 5 times, most recently from 8d9f910 to fc3f173 Compare February 24, 2023 20:34
@oas004 oas004 force-pushed the feature/custom-preview-annotation-support branch from fc3f173 to d277c86 Compare February 24, 2023 20:49
@oas004 oas004 requested a review from vinaygaba March 4, 2023 17:24
@oas004 oas004 force-pushed the feature/custom-preview-annotation-support branch from db3eafe to 7ccca0e Compare March 4, 2023 18:37
@oas004 oas004 requested a review from vinaygaba March 8, 2023 14:20
Copy link
Collaborator

@vinaygaba vinaygaba left a comment

Choose a reason for hiding this comment

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

Fantastic job on this PR 👏🏻 This has been a long time coming but I'm so glad you were able to be persistent and took care of all the cases that we could think of.

@anhanh11001
Copy link

@vinaygaba When this is merged, can you please also make a new release? This would help me with my work at work a lot! Thanks guys for this work 🙏

@oas004
Copy link
Contributor Author

oas004 commented Mar 9, 2023

Fantastic job on this PR 👏🏻 This has been a long time coming but I'm so glad you were able to be persistent and took care of all the cases that we could think of.

Wow this is awesome! 🥳 Thanks a lot for all the help and mentorship through the process! Learned a lot from this!

@vinaygaba vinaygaba merged commit d15c1f8 into airbnb:master Mar 10, 2023
@oas004 oas004 deleted the feature/custom-preview-annotation-support branch March 10, 2023 17:16
@anhanh11001
Copy link

Hi @oas004, I've tested this and it works really well. One question related to stacked custom preview, would something like this work?


@Preview(details1)
annotation class CustomPreview1

@Preview(details2)
annotation class CustomPreview2


@CustomPreview1
@CustomPreview2
annotation class CentralizedCustomPreview

@oas004
Copy link
Contributor Author

oas004 commented Mar 22, 2023

Hi @oas004, I've tested this and it works really well. One question related to stacked custom preview, would something like this work?


@Preview(details1)
annotation class CustomPreview1

@Preview(details2)
annotation class CustomPreview2


@CustomPreview1
@CustomPreview2
annotation class CentralizedCustomPreview

Hi @anhanh11001 :) So glad to hear that it is working! The case that you are describing should work for KSP. I think we have a test case for this here:https:/airbnb/Showkase/blob/master/showkase-processor-testing/src/test/resources/ShowkaseProcessorTest/composable_function_with_multiple_repeatable_custom_preview_annotation_generates_output/input/Composables.kt that is very similar :) Is it not working in your project?

@anhanh11001
Copy link

I see, I also use ksp. Then it could be something related to my setup. I'll double check. Thanks for confirming

@oas004
Copy link
Contributor Author

oas004 commented Mar 22, 2023

I think this should work out of the box if you are using KSP. I will try to check this out as well!

@takahirom
Copy link

I had the same problem and I found that we should apply ksp to the module we have the custom preview annotation.
https:/DroidKaigi/conference-app-2023/pull/605/files#diff-deb2ae6119caad892229b16120b0d33fe23ff75d1430dfb235c463482f10c386R10

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.

Support multi-preview annotations (annotations annotated with @Preview)
4 participants