Skip to content

Kotlin conversion of AboutActivity with tests also in Kotlin #2360

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

Conversation

juuce79
Copy link
Contributor

@juuce79 juuce79 commented Feb 26, 2025

  • Converted AboutActivity to kotlin from java.
  • Have tried to keep the code as close to the original as possible while using kotlin code instead of java code.
  • Added tests for AboutActivity.
  • Manually tested with APIs 24, 30 and 35 in Virtual Device in Android Studio.
  • This is part of my university project, to contribute to an open source project, and part of developer's plan to convert app to firstly Kotlin and eventually Jetpack Compose

@theimpulson
Copy link
Contributor

Related PRs that should be closed if this supersedes them:

OpenWebLinkHandler().openBrowser(this, tag)
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing new line EOF

Copy link
Contributor Author

@juuce79 juuce79 Feb 27, 2025

Choose a reason for hiding this comment

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

updated with @theimpulson's suggestion, now:
Applied the suggestion! Here's the updated code block showing the change:

143      private fun openExternalBrowser(view: View) {
144          val tag = view.tag
145          if (tag is String && tag.startsWith("https://")) {
146              OpenWebLinkHandler().openBrowser(this, tag)
147          }
148      }
149  }
150

Comment on lines 57 to 60
if (item.itemId == android.R.id.home) {
finish()
}
return super.onOptionsItemSelected(item)
Copy link
Contributor

Choose a reason for hiding this comment

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

You can consider using a when block here for a cleaner and easily extensible code.

Suggested change
if (item.itemId == android.R.id.home) {
finish()
}
return super.onOptionsItemSelected(item)
return when (item.itemId) {
android.R.id.home -> finish()
else -> super.onOptionsItemSelected(item)
}

Copy link
Contributor Author

@juuce79 juuce79 Feb 27, 2025

Choose a reason for hiding this comment

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

updated with @theimpulson's suggestion, now:

 56    override fun onOptionsItemSelected(item: MenuItem): Boolean {
 57        return when (item.itemId) {
 58            android.R.id.home -> {
 59                finish()
 60                true
 61            }
 62
 63            else -> super.onOptionsItemSelected(item)
 64        }
 65    }

Comment on lines 47 to 50
// Hide Google Play rate button if not on Google Play
rate.visibility = if (BuildConfig.showRateOnGooglePlay) View.VISIBLE else View.GONE
// Hide donate button on Google Play (Google Play doesn't allow donation links)
donate.visibility = if (BuildConfig.showDonate) View.VISIBLE else View.GONE
Copy link
Contributor

Choose a reason for hiding this comment

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

You can use the isVisible extension method from the core-ktx library here to make the logic more clean and simple.

Copy link
Contributor Author

@juuce79 juuce79 Feb 27, 2025

Choose a reason for hiding this comment

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

updated with @theimpulson's suggestion, now:

 47   // Hide Google Play rate button if not on Google Play
 48   rate.isVisible = BuildConfig.showRateOnGooglePlay
 49   // Hide donate button on Google Play (Google Play doesn't allow donation links)
 50   donate.isVisible = BuildConfig.showDonate

Comment on lines 21 to 22
private var _binding: AboutActivityBinding? = null
private val binding get() = _binding!!
Copy link
Contributor

Choose a reason for hiding this comment

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

This pattern of view binding is used for fragments and not activities. Please see this guide on patterns for activities.

Copy link
Contributor Author

@juuce79 juuce79 Feb 27, 2025

Choose a reason for hiding this comment

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

updated with @theimpulson's suggestion, now:

 22   private lateinit var binding: AboutActivityBinding

Comment on lines 63 to 68
override fun onDestroy() {
super.onDestroy()
content.destroy()
clearClickListeners()
_binding = null
}
Copy link
Contributor

Choose a reason for hiding this comment

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

These methods are not required for an Activity and should be dropped. They are only relevant for Fragment.

Copy link
Contributor Author

@juuce79 juuce79 Feb 27, 2025

Choose a reason for hiding this comment

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

updated with @theimpulson's suggestion, now:

 67    override fun onDestroy() {
 68        super.onDestroy()
 69        content.destroy()
 70        clearClickListeners()
 71    }

@juuce79
Copy link
Contributor Author

juuce79 commented Feb 27, 2025

@theimpulson I have updated the code with your suggestions and I was wondering, can I update this pull request with a new commit of the updated code (I haven't pushed or committed it to my fork yet so I don't mess anything up), or do I need to make a new pull request?
Regarding this code

    override fun onDestroy() {
        super.onDestroy()
        content.destroy()
        clearClickListeners()
        _binding = null
    }

I have just removed the _binding = null.

As this is being done as part of my university program and I am documenting the process, here is a PDF of the conversion process with the new updated code included:
catima_kotlin_conversion (2).pdf

Thanks for the help by the way, I and my partner (we are 2 working on this project) are still at university and have only had one Kotlin course so we are still new to Kotlin, and Java to be honest, although we have had quite a few Java courses so far. We are currently in our third year of our bachelors degree.

- added new line at EOF.
- changed if-else statement to `when` block for cleaner and more easily extensible code (lines 57-63).
- now using `isVisible` extension method from the core-ktx library to make the logic more clean and simple (lines 48 & 50).
- now using correct view binding pattern for activities (line 22).
- removed `_binding = null` from `onDestroy()` function (line 71).
@juuce79
Copy link
Contributor Author

juuce79 commented Feb 27, 2025

Updated with Aayush Gupta's suggestions:

  • added new line at EOF.
  • changed if-else statement to when block for cleaner and more easily extensible code (lines 57-63).
  • now using isVisible extension method from the core-ktx library to make the logic more clean and simple (lines 48 & 50).
  • now using correct view binding pattern for activities (line 22).
  • removed _binding = null from onDestroy() function (line 71).

@TheLastProject
Copy link
Member

Looks sensible to me. If @theimpulson thinks it's good now I'll do some quick on-device testing and hit merge :)

Comment on lines 55 to 62
val rateButton = activity.findViewById<View>(R.id.rate)
assertEquals(rateButton.visibility,
if (BuildConfig.showRateOnGooglePlay) View.VISIBLE else View.GONE)

// Test donate button visibility based on BuildConfig
val donateButton = activity.findViewById<View>(R.id.donate)
assertEquals(donateButton.visibility,
if (BuildConfig.showDonate) View.VISIBLE else View.GONE)
Copy link
Contributor

Choose a reason for hiding this comment

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

These could be switched to isVisible extension method as well like above for better readability.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated with @theimpulson's suggestion. Now:

 51    @Test
 52    fun testDisplayOptionsBasedOnConfig() {
 53        activityController.create().start().resume()
 54
 55        // Test Google Play rate button visibility based on BuildConfig
 56        val rateButton = activity.findViewById<View>(R.id.rate)
 57        assertEquals(BuildConfig.showRateOnGooglePlay, rateButton.isVisible)
 58
 59        // Test donate button visibility based on BuildConfig
 60        val donateButton = activity.findViewById<View>(R.id.donate)
 61        assertEquals(BuildConfig.showDonate, donateButton.isVisible)
 62    }

Comment on lines 150 to 158
// Get the current values from BuildConfig
val showRateOnGooglePlay = BuildConfig.showRateOnGooglePlay
val showDonate = BuildConfig.showDonate

// Test that the visibility matches the BuildConfig values
assertEquals(if (showRateOnGooglePlay) View.VISIBLE else View.GONE,
activity.findViewById<View>(R.id.rate).visibility)
assertEquals(if (showDonate) View.VISIBLE else View.GONE,
activity.findViewById<View>(R.id.donate).visibility)
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar suggestion to use isVisible like above

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated with @theimpulson's suggestion. Now:

145    @Test
146    fun testButtonVisibilityBasedOnBuildConfig() {
147        activityController.create().start().resume()
148
149        // Get the current values from BuildConfig
150        val showRateOnGooglePlay = BuildConfig.showRateOnGooglePlay
151        val showDonate = BuildConfig.showDonate
152
153        // Test that the visibility matches the BuildConfig values
154        assertEquals(showRateOnGooglePlay, activity.findViewById<View>(R.id.rate).isVisible)
155        assertEquals(showDonate, activity.findViewById<View>(R.id.donate).isVisible)
156    }

…tonVisibilityBasedOnBuildConfig` to use `isVisible` instead of checking visibility property directly with `View.VISIBLE/GONE` comparisons. This makes tests more consistent with implementation code in `AboutActivity.kt` and improves test readability.
@juuce79
Copy link
Contributor Author

juuce79 commented Feb 28, 2025

@theimpulson @TheLastProject Updated test functions testDisplayOptionsBasedOnConfig and testButtonVisibilityBasedOnBuildConfig to use isVisible instead of checking visibility property directly with View.VISIBLE/GONE comparisons. This makes tests more consistent with implementation code in AboutActivity.kt and improves test readability.

Copy link
Contributor

@theimpulson theimpulson left a comment

Choose a reason for hiding this comment

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

Looks good to me. Thank you.

@TheLastProject
Copy link
Member

Tested it and it works great. Thanks for the rewrite @juuce79 (and also thank you for the PDF file, it made understanding your changes a lot easier!). And thank you for the review, @theimpulson! :)

@TheLastProject TheLastProject merged commit 1a892b2 into CatimaLoyalty:main Mar 2, 2025
2 checks passed
@TheLastProject TheLastProject mentioned this pull request May 3, 2025
27 tasks
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.

3 participants