Skip to content

Commit 3566e04

Browse files
committed
Add Hilt
1 parent ed43019 commit 3566e04

File tree

76 files changed

+716
-569
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+716
-569
lines changed

app/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ plugins {
88
alias(libs.plugins.kotlin.kapt)
99
alias(libs.plugins.kotlin.parcelize)
1010
alias(libs.plugins.compose)
11+
alias(libs.plugins.hilt)
1112
}
1213

1314
apply(from = "$rootDir/jacoco.gradle")
@@ -287,6 +288,10 @@ dependencies {
287288
kapt(libs.dagger.compiler)
288289
annotationProcessor(libs.dagger.android.processor)
289290

291+
// Hilt
292+
implementation(libs.hilt.android)
293+
kapt(libs.hilt.compiler)
294+
290295
implementation(libs.kotlin.reflect)
291296

292297
//Mocking

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,13 @@
4646

4747
<application
4848
android:name=".CommonsApplication"
49-
android:appComponentFactory="commons"
5049
android:icon="@mipmap/ic_launcher"
5150
android:label="@string/app_name"
5251
android:largeHeap="true"
5352
android:requestLegacyExternalStorage="true"
5453
android:supportsRtl="true"
5554
android:theme="@style/LightAppTheme"
56-
tools:ignore="GoogleAppIndexingWarning"
57-
tools:replace="android:appComponentFactory">
55+
tools:ignore="GoogleAppIndexingWarning">
5856
<activity
5957
android:name=".activity.SingleWebViewActivity"
6058
android:exported="false" />

app/src/main/java/fr/free/nrw/commons/CommonsApplication.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import android.util.Log
1313
import androidx.multidex.MultiDexApplication
1414
import com.facebook.drawee.backends.pipeline.Fresco
1515
import com.facebook.imagepipeline.core.ImagePipelineConfig
16+
import dagger.hilt.android.HiltAndroidApp
1617
import fr.free.nrw.commons.auth.LoginActivity
1718
import fr.free.nrw.commons.auth.SessionManager
1819
import fr.free.nrw.commons.bookmarks.items.BookmarkItemsTable
@@ -22,7 +23,6 @@ import fr.free.nrw.commons.concurrency.BackgroundPoolExceptionHandler
2223
import fr.free.nrw.commons.concurrency.ThreadPoolService
2324
import fr.free.nrw.commons.contributions.ContributionDao
2425
import fr.free.nrw.commons.data.DBOpenHelper
25-
import fr.free.nrw.commons.di.ApplicationlessInjection
2626
import fr.free.nrw.commons.kvstore.JsonKvStore
2727
import fr.free.nrw.commons.language.AppLanguageLookUpTable
2828
import fr.free.nrw.commons.logging.FileLoggingTree
@@ -66,6 +66,7 @@ import javax.inject.Named
6666
resCommentPrompt = R.string.crash_dialog_comment_prompt
6767
)
6868

69+
@HiltAndroidApp
6970
class CommonsApplication : MultiDexApplication() {
7071

7172
@Inject
@@ -99,10 +100,8 @@ class CommonsApplication : MultiDexApplication() {
99100
instance = this
100101
init(this)
101102

102-
ApplicationlessInjection
103-
.getInstance(this)
104-
.commonsApplicationComponent
105-
.inject(this)
103+
// Hilt automatically injects dependencies for @HiltAndroidApp annotated classes
104+
// No manual injection needed
106105

107106
initTimber()
108107

app/src/main/java/fr/free/nrw/commons/activity/SingleWebViewActivity.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ import androidx.compose.runtime.mutableStateOf
2828
import androidx.compose.runtime.remember
2929
import androidx.compose.ui.Modifier
3030
import androidx.compose.ui.viewinterop.AndroidView
31+
import dagger.hilt.android.AndroidEntryPoint
3132
import fr.free.nrw.commons.CommonsApplication
3233
import fr.free.nrw.commons.CommonsApplication.ActivityLogoutListener
3334
import fr.free.nrw.commons.R
34-
import fr.free.nrw.commons.di.ApplicationlessInjection
3535
import fr.free.nrw.commons.wikidata.cookies.CommonsCookieJar
3636
import okhttp3.HttpUrl.Companion.toHttpUrl
3737
import timber.log.Timber
@@ -41,6 +41,7 @@ import javax.inject.Inject
4141
* SingleWebViewActivity is a reusable activity webView based on a given url(initial url) and
4242
* closes itself when a specified success URL is reached to success url.
4343
*/
44+
@AndroidEntryPoint
4445
class SingleWebViewActivity : ComponentActivity() {
4546
@Inject
4647
lateinit var cookieJar: CommonsCookieJar
@@ -54,10 +55,7 @@ class SingleWebViewActivity : ComponentActivity() {
5455
finish()
5556
return
5657
}
57-
ApplicationlessInjection
58-
.getInstance(applicationContext)
59-
.commonsApplicationComponent
60-
.inject(this)
58+
// Hilt automatically injects dependencies for @AndroidEntryPoint annotated classes
6159
setCookies(url)
6260
enableEdgeToEdge()
6361
setContent {

app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.kt

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
11
package fr.free.nrw.commons.auth
22

3-
import android.accounts.AccountAuthenticatorActivity
3+
import android.accounts.Account
4+
import android.accounts.AccountManager
45
import android.app.ProgressDialog
56
import android.content.Context
67
import android.content.DialogInterface
78
import android.content.Intent
89
import android.net.Uri
910
import android.os.Bundle
1011
import android.view.KeyEvent
11-
import android.view.MenuInflater
1212
import android.view.MenuItem
1313
import android.view.View
14-
import android.view.ViewGroup
1514
import android.view.inputmethod.EditorInfo
1615
import android.view.inputmethod.InputMethodManager
1716
import android.widget.TextView
1817
import androidx.annotation.ColorRes
1918
import androidx.annotation.StringRes
2019
import androidx.annotation.VisibleForTesting
2120
import androidx.appcompat.app.AlertDialog
22-
import androidx.appcompat.app.AppCompatDelegate
21+
import androidx.appcompat.app.AppCompatActivity
2322
import androidx.core.app.NavUtils
2423
import androidx.core.content.ContextCompat
2524
import androidx.core.view.WindowCompat
@@ -31,7 +30,6 @@ import fr.free.nrw.commons.auth.login.LoginClient
3130
import fr.free.nrw.commons.auth.login.LoginResult
3231
import fr.free.nrw.commons.contributions.MainActivity
3332
import fr.free.nrw.commons.databinding.ActivityLoginBinding
34-
import fr.free.nrw.commons.di.ApplicationlessInjection
3533
import fr.free.nrw.commons.kvstore.JsonKvStore
3634
import fr.free.nrw.commons.utils.applyEdgeToEdgeAllInsets
3735
import fr.free.nrw.commons.utils.AbstractTextWatcher
@@ -41,13 +39,15 @@ import fr.free.nrw.commons.utils.SystemThemeUtils
4139
import fr.free.nrw.commons.utils.ViewUtil.hideKeyboard
4240
import fr.free.nrw.commons.utils.handleKeyboardInsets
4341
import fr.free.nrw.commons.utils.handleWebUrl
42+
import dagger.hilt.android.AndroidEntryPoint
4443
import io.reactivex.disposables.CompositeDisposable
4544
import timber.log.Timber
4645
import java.util.Locale
4746
import javax.inject.Inject
4847
import javax.inject.Named
4948

50-
class LoginActivity : AccountAuthenticatorActivity() {
49+
@AndroidEntryPoint
50+
class LoginActivity : AppCompatActivity() {
5151
@Inject
5252
lateinit var sessionManager: SessionManager
5353

@@ -65,22 +65,14 @@ class LoginActivity : AccountAuthenticatorActivity() {
6565
private var progressDialog: ProgressDialog? = null
6666
private val textWatcher = AbstractTextWatcher(::onTextChanged)
6767
private val compositeDisposable = CompositeDisposable()
68-
private val delegate: AppCompatDelegate by lazy {
69-
AppCompatDelegate.create(this, null)
70-
}
7168
private var lastLoginResult: LoginResult? = null
7269

7370
public override fun onCreate(savedInstanceState: Bundle?) {
7471
super.onCreate(savedInstanceState)
75-
ApplicationlessInjection
76-
.getInstance(this.applicationContext)
77-
.commonsApplicationComponent
78-
.inject(this)
72+
// Hilt automatically injects dependencies for @AndroidEntryPoint annotated classes
7973

8074
val isDarkTheme = systemThemeUtils.isDeviceInNightMode()
8175
setTheme(if (isDarkTheme) R.style.DarkAppTheme else R.style.LightAppTheme)
82-
delegate.installViewFactory()
83-
delegate.onCreate(savedInstanceState)
8476

8577
WindowCompat.getInsetsController(window, window.decorView)
8678
.isAppearanceLightStatusBars = !isDarkTheme
@@ -170,7 +162,6 @@ class LoginActivity : AccountAuthenticatorActivity() {
170162
}
171163
override fun onPostCreate(savedInstanceState: Bundle?) {
172164
super.onPostCreate(savedInstanceState)
173-
delegate.onPostCreate(savedInstanceState)
174165
}
175166

176167
override fun onResume() {
@@ -201,29 +192,21 @@ class LoginActivity : AccountAuthenticatorActivity() {
201192
loginPassword.removeTextChangedListener(textWatcher)
202193
loginTwoFactor.removeTextChangedListener(textWatcher)
203194
}
204-
delegate.onDestroy()
205195
loginClient.cancel()
206196
binding = null
207197
super.onDestroy()
208198
}
209199

210200
override fun onStart() {
211201
super.onStart()
212-
delegate.onStart()
213202
}
214203

215204
override fun onStop() {
216205
super.onStop()
217-
delegate.onStop()
218206
}
219207

220208
override fun onPostResume() {
221209
super.onPostResume()
222-
delegate.onPostResume()
223-
}
224-
225-
override fun setContentView(view: View, params: ViewGroup.LayoutParams) {
226-
delegate.setContentView(view, params)
227210
}
228211

229212
override fun onOptionsItemSelected(item: MenuItem): Boolean {
@@ -237,6 +220,7 @@ class LoginActivity : AccountAuthenticatorActivity() {
237220
}
238221

239222
override fun onSaveInstanceState(outState: Bundle) {
223+
super.onSaveInstanceState(outState)
240224
// if progressDialog is visible during the configuration change then store state as true else false so that
241225
// we maintain visibility of progressDialog after configuration change
242226
if (progressDialog != null && progressDialog!!.isShowing) {
@@ -398,8 +382,6 @@ class LoginActivity : AccountAuthenticatorActivity() {
398382
startMainActivity()
399383
}
400384

401-
override fun getMenuInflater(): MenuInflater =
402-
delegate.menuInflater
403385

404386
@VisibleForTesting
405387
fun askUserForTwoFactorAuth() {
@@ -454,10 +436,33 @@ class LoginActivity : AccountAuthenticatorActivity() {
454436

455437
@VisibleForTesting
456438
fun startMainActivity() {
439+
// Handle account authentication result for AccountManager
440+
// Since we're now using AppCompatActivity instead of AccountAuthenticatorActivity
441+
val accountManager = AccountManager.get(this)
442+
val accountName = sessionManager.userName
443+
444+
if (accountName != null) {
445+
val account = Account(accountName, BuildConfig.ACCOUNT_TYPE)
446+
val intent = Intent()
447+
intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, accountName)
448+
intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, BuildConfig.ACCOUNT_TYPE)
449+
setAccountAuthenticatorResult(intent.extras)
450+
setResult(RESULT_OK, intent)
451+
}
452+
457453
startActivityWithFlags(this, MainActivity::class.java, Intent.FLAG_ACTIVITY_SINGLE_TOP)
458454
finish()
459455
}
460456

457+
// Helper method to set the account authenticator result
458+
private fun setAccountAuthenticatorResult(result: Bundle?) {
459+
// This would be called automatically in AccountAuthenticatorActivity
460+
// but we need to handle it manually now
461+
result?.let {
462+
intent.putExtras(it)
463+
}
464+
}
465+
461466
private fun showMessage(@StringRes resId: Int, @ColorRes colorResId: Int) = with(binding!!) {
462467
errorMessage.text = getString(resId)
463468
errorMessage.setTextColor(ContextCompat.getColor(this@LoginActivity, colorResId))

app/src/main/java/fr/free/nrw/commons/auth/WikiAccountAuthenticatorService.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package fr.free.nrw.commons.auth
33
import android.accounts.AbstractAccountAuthenticator
44
import android.content.Intent
55
import android.os.IBinder
6+
import dagger.hilt.android.AndroidEntryPoint
67
import fr.free.nrw.commons.di.CommonsDaggerService
78

89
/**
910
* Handles the Auth service of the App, see AndroidManifests for details
1011
* (Uses Dagger 2 as injector)
1112
*/
13+
@AndroidEntryPoint
1214
class WikiAccountAuthenticatorService : CommonsDaggerService() {
1315
private var authenticator: AbstractAccountAuthenticator? = null
1416

app/src/main/java/fr/free/nrw/commons/bookmarks/BookmarkFragment.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import fr.free.nrw.commons.databinding.FragmentBookmarksBinding
1010
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment
1111
import fr.free.nrw.commons.kvstore.JsonKvStore
1212
import fr.free.nrw.commons.theme.BaseActivity
13+
import dagger.hilt.android.AndroidEntryPoint
1314
import javax.inject.Inject
1415
import javax.inject.Named
1516

17+
@AndroidEntryPoint
1618
class BookmarkFragment : CommonsDaggerSupportFragment() {
1719
private var adapter: BookmarksPagerAdapter? = null
1820

app/src/main/java/fr/free/nrw/commons/bookmarks/BookmarkListRootFragment.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ import fr.free.nrw.commons.media.MediaDetailPagerFragment
2323
import fr.free.nrw.commons.media.MediaDetailPagerFragment.Companion.newInstance
2424
import fr.free.nrw.commons.media.MediaDetailProvider
2525
import fr.free.nrw.commons.navtab.NavTab
26+
import dagger.hilt.android.AndroidEntryPoint
2627
import timber.log.Timber
2728

29+
@AndroidEntryPoint
2830
class BookmarkListRootFragment : CommonsDaggerSupportFragment,
2931
FragmentManager.OnBackStackChangedListener, MediaDetailProvider, OnItemClickListener,
3032
CategoryImagesCallback {

app/src/main/java/fr/free/nrw/commons/bookmarks/items/BookmarkItemsContentProvider.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,42 @@ import android.content.ContentValues
44
import android.database.Cursor
55
import android.database.sqlite.SQLiteQueryBuilder
66
import android.net.Uri
7+
import dagger.hilt.EntryPoint
8+
import dagger.hilt.InstallIn
9+
import dagger.hilt.android.EntryPointAccessors
10+
import dagger.hilt.components.SingletonComponent
711
import fr.free.nrw.commons.BuildConfig
812
import fr.free.nrw.commons.bookmarks.items.BookmarkItemsTable.TABLE_NAME
13+
import fr.free.nrw.commons.data.DBOpenHelper
914
import fr.free.nrw.commons.di.CommonsDaggerContentProvider
1015
import androidx.core.net.toUri
1116
import fr.free.nrw.commons.bookmarks.items.BookmarkItemsTable.COLUMN_ID
1217

18+
/**
19+
* Entry point for injecting dependencies into BookmarkItemsContentProvider
20+
* ContentProviders cannot use @AndroidEntryPoint, so we use @EntryPoint instead
21+
*/
22+
@EntryPoint
23+
@InstallIn(SingletonComponent::class)
24+
interface BookmarkItemsContentProviderEntryPoint {
25+
fun dbOpenHelper(): DBOpenHelper
26+
}
27+
1328
/**
1429
* Handles private storage for bookmarked items
1530
*/
1631
class BookmarkItemsContentProvider : CommonsDaggerContentProvider() {
32+
33+
override fun onCreate(): Boolean {
34+
// Initialize dbOpenHelper using EntryPoint since ContentProviders don't support @AndroidEntryPoint
35+
val entryPoint = EntryPointAccessors.fromApplication(
36+
context!!.applicationContext,
37+
BookmarkItemsContentProviderEntryPoint::class.java
38+
)
39+
dbOpenHelper = entryPoint.dbOpenHelper()
40+
return true
41+
}
42+
1743
override fun getType(uri: Uri): String? = null
1844

1945
/**

app/src/main/java/fr/free/nrw/commons/bookmarks/pictures/BookmarkPicturesContentProvider.kt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,42 @@ import android.content.ContentValues
44
import android.database.Cursor
55
import android.database.sqlite.SQLiteQueryBuilder
66
import android.net.Uri
7+
import dagger.hilt.EntryPoint
8+
import dagger.hilt.InstallIn
9+
import dagger.hilt.android.EntryPointAccessors
10+
import dagger.hilt.components.SingletonComponent
711
import fr.free.nrw.commons.BuildConfig
12+
import fr.free.nrw.commons.data.DBOpenHelper
813
import fr.free.nrw.commons.di.CommonsDaggerContentProvider
914
import androidx.core.net.toUri
1015
import fr.free.nrw.commons.bookmarks.pictures.BookmarksTable.COLUMN_MEDIA_NAME
1116
import fr.free.nrw.commons.bookmarks.pictures.BookmarksTable.TABLE_NAME
1217

18+
/**
19+
* Entry point for injecting dependencies into BookmarkPicturesContentProvider
20+
* ContentProviders cannot use @AndroidEntryPoint, so we use @EntryPoint instead
21+
*/
22+
@EntryPoint
23+
@InstallIn(SingletonComponent::class)
24+
interface BookmarkPicturesContentProviderEntryPoint {
25+
fun dbOpenHelper(): DBOpenHelper
26+
}
27+
1328
/**
1429
* Handles private storage for Bookmark pictures
1530
*/
1631
class BookmarkPicturesContentProvider : CommonsDaggerContentProvider() {
32+
33+
override fun onCreate(): Boolean {
34+
// Initialize dbOpenHelper using EntryPoint since ContentProviders don't support @AndroidEntryPoint
35+
val entryPoint = EntryPointAccessors.fromApplication(
36+
context!!.applicationContext,
37+
BookmarkPicturesContentProviderEntryPoint::class.java
38+
)
39+
dbOpenHelper = entryPoint.dbOpenHelper()
40+
return true
41+
}
42+
1743
override fun getType(uri: Uri): String? = null
1844

1945
/**

0 commit comments

Comments
 (0)