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 first steps: Welcome screen and build.gradle code injection screens #1

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

nan-li
Copy link
Contributor

@nan-li nan-li commented May 2, 2022

Background Information

This project was created in IntelliJ IDEA 2020.3.3 (Build #IC-203.7717.56) with Java 11.

There may be compatibility challenges. I would like to know if you are able to open this project, build it, or add it to another Android project, and what errors you encounter.

I am also not sure if the build.gradle contents are best.

Design and Copy

For now, there was not a focus on the text, wording, or design. Some of the text is inaccurate too. It is mainly focused on the logic so any words or styles are temporary and should be changed.

Panels

In this PR, there are 3 panels (screens) created.

1: Welcome Screen

Welcome Screen

2: Project-Level build.gradle Code Injection Screen

Project build.gradle Code Injection Screen

  • Managed by classes SDKSetupFirstStepPanel and SDKSetupFirstStepController.
  • Injects gradlePluginPortal() if not there to buildscript > repositories
  • Injects "classpath 'gradle.plugin.com.onesignal:onesignal-gradle-plugin:[0.12.9, 0.99.99]'" if not there to buildscript > dependencies
  • Clicking the Next button will apply the changes and take the the user to the next screen.
  • Cancel button takes the user to the Welcome Screen.

3: App-Level build.gradle Code Injection Screen

App build.gradle Code Injection Screen

  • Managed by classes SDKSetupSecondStepPanel and SDKSetupSecondStepController.
  • Injects "implementation 'com.onesignal:OneSignal:[4.0.0, 4.99.99]'".
  • Injects plugin com.onesignal.androidsdk.onesignal-gradle-plugin
  • By default, uses path BASE_PROJECT_PATH/app/build.gradle to find the file. If the project structure is different, such as is the example project in the OneSignal-Android-SDK, the user will have to input their full path into the text box.
  • Clicking the Next button will apply the changes and take the user to the next screen (a success screen that will be added).
  • Cancel button takes the user to the Welcome Screen.

Functions

String.appendStringByMatch() is the primary helper function to inject code into the user's files.

  • The receiver is the entire string content of a file such as build.gradle.
  • The function checks for the existence of a substring we want to inject (to avoid adding duplicate code the user already has) such as "com.onesignal:OneSignal" before adding that dependency.
  • We also provide an anchor substring that we expect to be in the file, so that we inject the new string to the end of that. For example, an anchor substring could be "mavenCentral()" at the end of which we inject "gradlePluginPortal()".
  • If none of the expected anchor substrings exist, and we should be injecting our code, then the code will not be injected. This is an error and should be tracked.

Limitations and Improvements

  • Relies heavily on text markers and regular expressions for code injection
  • As a result of the above, the plugin will find the first match when injecting code. For example, adding gradlePluginPortal() looks for jcenter() or mavenCentral() to anchor to, but if the user has mavenCentral() in allprojects first and buildscript later in the file, the plugin will inject the code under allprojects.
  • Currently does separate checks for if file uses double quotes "" or single quotes '', which can be made cleaner
  • User's indentation may be different (the indentation is hardcoded for injecting code)

Testing

I manually tested using the OneSignal-Android-SDK example app, another Java project, and a new Kotlin Android Studio project.

How to Run

  1. Open the project in IntelliJ IDEA, and build with ./gradlew clean build. When I build on IDEA 2020.3.3, I do get an error in buildSearchableOptions that is this issue (it should still build successfully even with the error output).
  2. In Android Studio, go to Preferences > Plugins > Gear icon on the top right > Install Plugin From Disk... Navigate to the build folder of OneSignal-AS-Plugin and select the .jar you just built. You should be prompted to Restart the IDE as well.
  3. If you make changes to your gradle files during testing, you may need to sync the gradle files for the plugin to have the latest changes.

nan-li added 3 commits April 20, 2022 03:00
Set up the tool window that will be displayed and the first screen that users will see, the welcome screen.
- This is the first SDK setup step (after the welcome screen)

- Adds next button to welcome screen to get to this step
- Injects `gradlePluginPortal()` and `classpath "gradle.plugin.com.onesignal:onesignal-gradle-plugin:[0.12.9, 0.99.99]"`
- This is the second SDK setup step (after the welcome screen and project build.gradle)

- Injects `implementation 'com.onesignal:OneSignal:[4.0.0, 4.99.99]'` and `apply plugin: 'com.onesignal.androidsdk.onesignal-gradle-plugin'`

- If project directory is not just BASE_PROJECT_PATH/app/build.gradle, the user has to specify the path, for example `~/Documents/outerProject/subProject/app`
@nan-li nan-li changed the title Add first steps: welcome and build.gradle code injection Add first steps: Welcome screen and build.gradle code injection screens May 2, 2022
@nan-li nan-li force-pushed the feat/add_gradle_code_injection branch from dfc729c to 22c9ccc Compare May 2, 2022 22:43
nan-li added 5 commits May 2, 2022 15:54
* Check for a different substring (named appendId) to avoid adding duplicate code if it already exists. This will avoid overlooking dependencies with version variables.

* For example, check for the existance of "com.onesignal:OneSignal" instead of "implementation 'com.onesignal:OneSignal:[4.0.0, 4.99.99]'" when deciding to inject the latter.
* Add home navigation by cancel button
Placeholder for the plugin icon
These were not in my files and everything ran ok, but adding them in case they are actually needed
- add showNotification to utils

- it helps to debug while working, to see what values are

- use showNotification in code, and need to pass project to use it

- this will be removed later, for debugging purposes only for now
@nan-li nan-li force-pushed the feat/add_gradle_code_injection branch from 22c9ccc to 246e679 Compare May 2, 2022 22:57
@nan-li nan-li requested a review from a team May 3, 2022 20:02

dependencies {

classpath 'com.onesignal:onesignal-gradle-plugin:[0.8.1, 0.99.99]'
Copy link
Member

Choose a reason for hiding this comment

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

Update to latest version, which is 0.14.0. Also we should probably have a shared definition for this version string, since it is used in multiple spots.

val appendIdMatch = appendIdRegex.find(this)?.range

showNotification(project, "appendId string: $appendId match: $appendIdMatch")
return if (appendIdMatch == null) {
Copy link
Member

Choose a reason for hiding this comment

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

This would be easier to read as early returns, instead of a large nested if-else block. Smaller if-else blocks can make code easier to read than some other ways, but this one is pretty long.

// injecting com.onesignal:OneSignal dependency

content = content.appendStringByMatch(
"implementation \"androidx.appcompat:appcompat:[^']*\"",
Copy link
Member

Choose a reason for hiding this comment

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

These string searches look to be checking some possible dependences that the project might have. This doesn't look like it can account for any unexpected dependency so it looks like this approach won't work with may projects.

Did some searching and it looks like there is an Intellij API to read the build.gradle file and modify it (com.android.tools.idea.gradle.dsl.model.GradleBuildModel):
https://intellij-support.jetbrains.com/hc/en-us/community/posts/115000106044-How-to-add-dependencies-to-gradle-file-from-IntelliJ-DEA-plugin-

}

//runIde {
Copy link
Member

Choose a reason for hiding this comment

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

Can we remove this? Or add a comment of a reason why you would want to uncomment this, such as to test something specific.

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.

2 participants