Skip to content

Commit 5d4474e

Browse files
Migrated AboutActivity from Java to Kotlin (#6158)
* Rename Constants to Follow Kotlin Naming Conventions >This PR refactors constant names in the project to adhere to Kotlin's UPPERCASE_SNAKE_CASE naming convention, improving code readability and maintaining consistency across the codebase. >Renamed the following constants in LoginActivity: >saveProgressDialog → SAVE_PROGRESS_DIALOG >saveErrorMessage → SAVE_ERROR_MESSAGE >saveUsername → SAVE_USERNAME >savePassword → SAVE_PASSWORD >Updated all references to these constants throughout the project. * Update Project_Default.xml * Refactor variable names to adhere to naming conventions Renamed variables to use camel case: -UPLOAD_COUNT_THRESHOLD → uploadCountThreshold -REVERT_PERCENTAGE_FOR_MESSAGE → revertPercentageForMessage -REVERT_SHARED_PREFERENCE → revertSharedPreference -UPLOAD_SHARED_PREFERENCE → uploadSharedPreference Renamed variables with uppercase initials to lowercase for alignment with Kotlin conventions: -Latitude → latitude -Longitude → longitude -Accuracy → accuracy Refactored the following variable names: -NUMBER_OF_QUESTIONS → numberOfQuestions -MULTIPLIER_TO_GET_PERCENTAGE → multiplierToGetPercentage * Refactor Dialog View Initialization with Null-Safe Calls This PR refactors the dialog setup code in CustomSelectorActivity to improve safety and readability by replacing explicit casts with null-safe generic calls for findViewById. >Replaced explicit casting (as Button and as TextView) with the generic findViewById<T>() method for improved type safety. >Added null-safety (?.) to avoid potential crashes if a view is not found in the dialog layout. why changed:- >Prevents runtime crashes caused by NullPointerException when a view is missing in the layout. * Refactor Unit Test: Replace Unsafe Casting with Type-Safe Mocking for findViewById >PR refactors the unit test for NearbyParentFragment by replacing unsafe casting in the findViewById mocking statements with type-safe >Ensured all findViewById mocks now use a consistent, type-safe format (findViewById<View>(...)) to reduce verbosity and potential casting errors. >Verified the functionality of prepareViewsForSheetPosition remains unchanged, ensuring no regression in test behavior. * Update NearbyParentFragmentUnitTest.kt * Refactor: Rename Constants to Follow CamelCase Naming Convention >Updated all constant variable names to follow the camelCase naming convention, removing underscores in the middle or end. >Ensured variable names remain descriptive and align with code readability best practices. * Replace private val with const val for URL constants in QuizController * Renaming the constant to use UPPER_SNAKE_CASE * Renaming the constant to use UPPER_SNAKE_CASE * Update Done * **Refactor: Convert `minimumThresholdForSwipe` to a compile-time constant** * Convert AboutActivity from Java to Kotlin This PR converts the AboutActivity class from Java to Kotlin >Testing: >Verified all functionalities of the AboutActivity, including toolbar setup, intent launches, and dialog interactions, to ensure behavior remains consistent post-conversion. >Successfully ran unit tests for AboutActivity to confirm the correctness of methods and logic. * Thank you for the suggestion! Since these methods all take a single View parameter, replacing them with method references is a great way to simplify the code and improve readability. I'll updated the code accordingly. Added a TODO in the code as a reminder to refactor this in the future. --------- Co-authored-by: Nicolas Raoul <[email protected]>
1 parent 36f844a commit 5d4474e

File tree

2 files changed

+209
-187
lines changed

2 files changed

+209
-187
lines changed

app/src/main/java/fr/free/nrw/commons/AboutActivity.java

Lines changed: 0 additions & 187 deletions
This file was deleted.
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
package fr.free.nrw.commons
2+
3+
import android.annotation.SuppressLint
4+
import android.content.Intent
5+
import android.net.Uri
6+
import android.os.Bundle
7+
import android.view.Menu
8+
import android.view.MenuItem
9+
import android.view.View
10+
import android.widget.ArrayAdapter
11+
import android.widget.LinearLayout
12+
import android.widget.Spinner
13+
import fr.free.nrw.commons.CommonsApplication.Companion.instance
14+
import fr.free.nrw.commons.databinding.ActivityAboutBinding
15+
import fr.free.nrw.commons.theme.BaseActivity
16+
import fr.free.nrw.commons.utils.ConfigUtils.getVersionNameWithSha
17+
import fr.free.nrw.commons.utils.DialogUtil.showAlertDialog
18+
import java.util.Collections
19+
20+
/**
21+
* Represents about screen of this app
22+
*/
23+
class AboutActivity : BaseActivity() {
24+
/*
25+
This View Binding class is auto-generated for each xml file. The format is usually the name
26+
of the file with PascalCasing (The underscore characters will be ignored).
27+
More information is available at https://developer.android.com/topic/libraries/view-binding
28+
*/
29+
private var binding: ActivityAboutBinding? = null
30+
31+
/**
32+
* This method helps in the creation About screen
33+
*
34+
* @param savedInstanceState Data bundle
35+
*/
36+
@SuppressLint("StringFormatInvalid") //TODO:
37+
public override fun onCreate(savedInstanceState: Bundle?) {
38+
super.onCreate(savedInstanceState)
39+
40+
/*
41+
Instead of just setting the view with the xml file. We need to use View Binding class.
42+
*/
43+
binding = ActivityAboutBinding.inflate(layoutInflater)
44+
val view: View = binding!!.root
45+
setContentView(view)
46+
47+
setSupportActionBar(binding!!.toolbarBinding.toolbar)
48+
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
49+
val aboutText = getString(R.string.about_license)
50+
/*
51+
We can then access all the views by just using the id names like this.
52+
camelCasing is used with underscore characters being ignored.
53+
*/
54+
binding!!.aboutLicense.setHtmlText(aboutText)
55+
56+
@SuppressLint("StringFormatMatches") // TODO:
57+
val improveText =
58+
String.format(getString(R.string.about_improve), Urls.NEW_ISSUE_URL)
59+
binding!!.aboutImprove.setHtmlText(improveText)
60+
binding!!.aboutVersion.text = applicationContext.getVersionNameWithSha()
61+
62+
Utils.setUnderlinedText(
63+
binding!!.aboutFaq, R.string.about_faq,
64+
applicationContext
65+
)
66+
Utils.setUnderlinedText(
67+
binding!!.aboutRateUs, R.string.about_rate_us,
68+
applicationContext
69+
)
70+
Utils.setUnderlinedText(
71+
binding!!.aboutUserGuide, R.string.user_guide,
72+
applicationContext
73+
)
74+
Utils.setUnderlinedText(
75+
binding!!.aboutPrivacyPolicy, R.string.about_privacy_policy,
76+
applicationContext
77+
)
78+
Utils.setUnderlinedText(
79+
binding!!.aboutTranslate, R.string.about_translate,
80+
applicationContext
81+
)
82+
Utils.setUnderlinedText(
83+
binding!!.aboutCredits, R.string.about_credits,
84+
applicationContext
85+
)
86+
87+
/*
88+
To set listeners, we can create a separate method and use lambda syntax.
89+
*/
90+
binding!!.facebookLaunchIcon.setOnClickListener(::launchFacebook)
91+
binding!!.githubLaunchIcon.setOnClickListener(::launchGithub)
92+
binding!!.websiteLaunchIcon.setOnClickListener(::launchWebsite)
93+
binding!!.aboutRateUs.setOnClickListener(::launchRatings)
94+
binding!!.aboutCredits.setOnClickListener(::launchCredits)
95+
binding!!.aboutPrivacyPolicy.setOnClickListener(::launchPrivacyPolicy)
96+
binding!!.aboutUserGuide.setOnClickListener(::launchUserGuide)
97+
binding!!.aboutFaq.setOnClickListener(::launchFrequentlyAskedQuesions)
98+
binding!!.aboutTranslate.setOnClickListener(::launchTranslate)
99+
}
100+
101+
override fun onSupportNavigateUp(): Boolean {
102+
onBackPressed()
103+
return true
104+
}
105+
106+
fun launchFacebook(view: View?) {
107+
val intent: Intent
108+
try {
109+
intent = Intent(Intent.ACTION_VIEW, Uri.parse(Urls.FACEBOOK_APP_URL))
110+
intent.setPackage(Urls.FACEBOOK_PACKAGE_NAME)
111+
startActivity(intent)
112+
} catch (e: Exception) {
113+
Utils.handleWebUrl(this, Uri.parse(Urls.FACEBOOK_WEB_URL))
114+
}
115+
}
116+
117+
fun launchGithub(view: View?) {
118+
val intent: Intent
119+
try {
120+
intent = Intent(Intent.ACTION_VIEW, Uri.parse(Urls.GITHUB_REPO_URL))
121+
intent.setPackage(Urls.GITHUB_PACKAGE_NAME)
122+
startActivity(intent)
123+
} catch (e: Exception) {
124+
Utils.handleWebUrl(this, Uri.parse(Urls.GITHUB_REPO_URL))
125+
}
126+
}
127+
128+
fun launchWebsite(view: View?) {
129+
Utils.handleWebUrl(this, Uri.parse(Urls.WEBSITE_URL))
130+
}
131+
132+
fun launchRatings(view: View?) {
133+
Utils.rateApp(this)
134+
}
135+
136+
fun launchCredits(view: View?) {
137+
Utils.handleWebUrl(this, Uri.parse(Urls.CREDITS_URL))
138+
}
139+
140+
fun launchUserGuide(view: View?) {
141+
Utils.handleWebUrl(this, Uri.parse(Urls.USER_GUIDE_URL))
142+
}
143+
144+
fun launchPrivacyPolicy(view: View?) {
145+
Utils.handleWebUrl(this, Uri.parse(BuildConfig.PRIVACY_POLICY_URL))
146+
}
147+
148+
fun launchFrequentlyAskedQuesions(view: View?) {
149+
Utils.handleWebUrl(this, Uri.parse(Urls.FAQ_URL))
150+
}
151+
152+
override fun onCreateOptionsMenu(menu: Menu): Boolean {
153+
val inflater = menuInflater
154+
inflater.inflate(R.menu.menu_about, menu)
155+
return super.onCreateOptionsMenu(menu)
156+
}
157+
158+
override fun onOptionsItemSelected(item: MenuItem): Boolean {
159+
when (item.itemId) {
160+
R.id.share_app_icon -> {
161+
val shareText = String.format(
162+
getString(R.string.share_text),
163+
Urls.PLAY_STORE_URL_PREFIX + this.packageName
164+
)
165+
val sendIntent = Intent()
166+
sendIntent.setAction(Intent.ACTION_SEND)
167+
sendIntent.putExtra(Intent.EXTRA_TEXT, shareText)
168+
sendIntent.setType("text/plain")
169+
startActivity(Intent.createChooser(sendIntent, getString(R.string.share_via)))
170+
return true
171+
}
172+
173+
else -> return super.onOptionsItemSelected(item)
174+
}
175+
}
176+
177+
fun launchTranslate(view: View?) {
178+
val sortedLocalizedNamesRef = instance.languageLookUpTable!!.getCanonicalNames()
179+
Collections.sort(sortedLocalizedNamesRef)
180+
val languageAdapter = ArrayAdapter(
181+
this@AboutActivity,
182+
android.R.layout.simple_spinner_dropdown_item, sortedLocalizedNamesRef
183+
)
184+
val spinner = Spinner(this@AboutActivity)
185+
spinner.layoutParams =
186+
LinearLayout.LayoutParams(
187+
LinearLayout.LayoutParams.WRAP_CONTENT,
188+
LinearLayout.LayoutParams.WRAP_CONTENT
189+
)
190+
spinner.adapter = languageAdapter
191+
spinner.gravity = 17
192+
spinner.setPadding(50, 0, 0, 0)
193+
194+
val positiveButtonRunnable = Runnable {
195+
val langCode = instance.languageLookUpTable!!.getCodes()[spinner.selectedItemPosition]
196+
Utils.handleWebUrl(this@AboutActivity, Uri.parse(Urls.TRANSLATE_WIKI_URL + langCode))
197+
}
198+
showAlertDialog(
199+
this,
200+
getString(R.string.about_translate_title),
201+
getString(R.string.about_translate_message),
202+
getString(R.string.about_translate_proceed),
203+
getString(R.string.about_translate_cancel),
204+
positiveButtonRunnable,
205+
{},
206+
spinner
207+
)
208+
}
209+
}

0 commit comments

Comments
 (0)