Convert CommonsApplicationModule to kotlin

This commit is contained in:
Paul Hawke 2024-11-28 22:14:29 -06:00
parent 04bee0ed01
commit 2536574f5d
3 changed files with 245 additions and 324 deletions

View file

@ -1,314 +0,0 @@
package fr.free.nrw.commons.di;
import android.app.Activity;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.view.inputmethod.InputMethodManager;
import androidx.collection.LruCache;
import androidx.room.Room;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;
import com.google.gson.Gson;
import dagger.Module;
import dagger.Provides;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.contributions.ContributionDao;
import fr.free.nrw.commons.customselector.database.NotForUploadStatusDao;
import fr.free.nrw.commons.customselector.database.UploadedStatusDao;
import fr.free.nrw.commons.customselector.ui.selector.ImageFileLoader;
import fr.free.nrw.commons.data.DBOpenHelper;
import fr.free.nrw.commons.db.AppDatabase;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.location.LocationServiceManager;
import fr.free.nrw.commons.nearby.PlaceDao;
import fr.free.nrw.commons.review.ReviewDao;
import fr.free.nrw.commons.settings.Prefs;
import fr.free.nrw.commons.upload.UploadController;
import fr.free.nrw.commons.upload.depicts.DepictsDao;
import fr.free.nrw.commons.utils.ConfigUtils;
import fr.free.nrw.commons.wikidata.WikidataEditListener;
import fr.free.nrw.commons.wikidata.WikidataEditListenerImpl;
import io.reactivex.Scheduler;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.inject.Named;
import javax.inject.Singleton;
/**
* The Dependency Provider class for Commons Android.
*
* Provides all sorts of ContentProviderClients used by the app
* along with the Liscences, AccountUtility, UploadController, Logged User,
* Location manager etc
*/
@Module
@SuppressWarnings({"WeakerAccess", "unused"})
public class CommonsApplicationModule {
private Context applicationContext;
public static final String IO_THREAD="io_thread";
public static final String MAIN_THREAD="main_thread";
private AppDatabase appDatabase;
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE contribution "
+ " ADD COLUMN hasInvalidLocation INTEGER NOT NULL DEFAULT 0");
}
};
public CommonsApplicationModule(Context applicationContext) {
this.applicationContext = applicationContext;
}
/**
* Provides ImageFileLoader used to fetch device images.
* @param context
* @return
*/
@Provides
public ImageFileLoader providesImageFileLoader(Context context) {
return new ImageFileLoader(context);
}
@Provides
public Context providesApplicationContext() {
return this.applicationContext;
}
@Provides
public InputMethodManager provideInputMethodManager() {
return (InputMethodManager) applicationContext.getSystemService(Activity.INPUT_METHOD_SERVICE);
}
@Provides
@Named("licenses")
public List<String> provideLicenses(Context context) {
List<String> licenseItems = new ArrayList<>();
licenseItems.add(context.getString(R.string.license_name_cc0));
licenseItems.add(context.getString(R.string.license_name_cc_by));
licenseItems.add(context.getString(R.string.license_name_cc_by_sa));
licenseItems.add(context.getString(R.string.license_name_cc_by_four));
licenseItems.add(context.getString(R.string.license_name_cc_by_sa_four));
return licenseItems;
}
@Provides
@Named("licenses_by_name")
public Map<String, String> provideLicensesByName(Context context) {
Map<String, String> byName = new HashMap<>();
byName.put(context.getString(R.string.license_name_cc0), Prefs.Licenses.CC0);
byName.put(context.getString(R.string.license_name_cc_by), Prefs.Licenses.CC_BY_3);
byName.put(context.getString(R.string.license_name_cc_by_sa), Prefs.Licenses.CC_BY_SA_3);
byName.put(context.getString(R.string.license_name_cc_by_four), Prefs.Licenses.CC_BY_4);
byName.put(context.getString(R.string.license_name_cc_by_sa_four), Prefs.Licenses.CC_BY_SA_4);
return byName;
}
/**
* Provides an instance of CategoryContentProviderClient i.e. the categories
* that are there in local storage
*/
@Provides
@Named("category")
public ContentProviderClient provideCategoryContentProviderClient(Context context) {
return context.getContentResolver().acquireContentProviderClient(BuildConfig.CATEGORY_AUTHORITY);
}
/**
* This method is used to provide instance of RecentSearchContentProviderClient
* which provides content of Recent Searches from database
* @param context
* @return returns RecentSearchContentProviderClient
*/
@Provides
@Named("recentsearch")
public ContentProviderClient provideRecentSearchContentProviderClient(Context context) {
return context.getContentResolver().acquireContentProviderClient(BuildConfig.RECENT_SEARCH_AUTHORITY);
}
@Provides
@Named("contribution")
public ContentProviderClient provideContributionContentProviderClient(Context context) {
return context.getContentResolver().acquireContentProviderClient(BuildConfig.CONTRIBUTION_AUTHORITY);
}
@Provides
@Named("modification")
public ContentProviderClient provideModificationContentProviderClient(Context context) {
return context.getContentResolver().acquireContentProviderClient(BuildConfig.MODIFICATION_AUTHORITY);
}
@Provides
@Named("bookmarks")
public ContentProviderClient provideBookmarkContentProviderClient(Context context) {
return context.getContentResolver().acquireContentProviderClient(BuildConfig.BOOKMARK_AUTHORITY);
}
@Provides
@Named("bookmarksLocation")
public ContentProviderClient provideBookmarkLocationContentProviderClient(Context context) {
return context.getContentResolver().acquireContentProviderClient(BuildConfig.BOOKMARK_LOCATIONS_AUTHORITY);
}
@Provides
@Named("bookmarksItem")
public ContentProviderClient provideBookmarkItemContentProviderClient(Context context) {
return context.getContentResolver().acquireContentProviderClient(BuildConfig.BOOKMARK_ITEMS_AUTHORITY);
}
/**
* This method is used to provide instance of RecentLanguagesContentProvider
* which provides content of recent used languages from database
* @param context Context
* @return returns RecentLanguagesContentProvider
*/
@Provides
@Named("recent_languages")
public ContentProviderClient provideRecentLanguagesContentProviderClient(final Context context) {
return context.getContentResolver()
.acquireContentProviderClient(BuildConfig.RECENT_LANGUAGE_AUTHORITY);
}
/**
* Provides a Json store instance(JsonKvStore) which keeps
* the provided Gson in it's instance
* @param gson stored inside the store instance
*/
@Provides
@Named("default_preferences")
public JsonKvStore providesDefaultKvStore(Context context, Gson gson) {
String storeName = context.getPackageName() + "_preferences";
return new JsonKvStore(context, storeName, gson);
}
@Provides
public UploadController providesUploadController(SessionManager sessionManager,
@Named("default_preferences") JsonKvStore kvStore,
Context context, ContributionDao contributionDao) {
return new UploadController(sessionManager, context, kvStore);
}
@Provides
@Singleton
public LocationServiceManager provideLocationServiceManager(Context context) {
return new LocationServiceManager(context);
}
@Provides
@Singleton
public DBOpenHelper provideDBOpenHelper(Context context) {
return new DBOpenHelper(context);
}
@Provides
@Singleton
@Named("thumbnail-cache")
public LruCache<String, String> provideLruCache() {
return new LruCache<>(1024);
}
@Provides
@Singleton
public WikidataEditListener provideWikidataEditListener() {
return new WikidataEditListenerImpl();
}
/**
* Provides app flavour. Can be used to alter flows in the app
* @return
*/
@Named("isBeta")
@Provides
@Singleton
public boolean provideIsBetaVariant() {
return ConfigUtils.isBetaFlavour();
}
/**
* Provide JavaRx IO scheduler which manages IO operations
* across various Threads
*/
@Named(IO_THREAD)
@Provides
public Scheduler providesIoThread(){
return Schedulers.io();
}
@Named(MAIN_THREAD)
@Provides
public Scheduler providesMainThread() {
return AndroidSchedulers.mainThread();
}
@Named("username")
@Provides
public String provideLoggedInUsername(SessionManager sessionManager) {
return Objects.toString(sessionManager.getUserName(), "");
}
@Provides
@Singleton
public AppDatabase provideAppDataBase() {
appDatabase = Room.databaseBuilder(applicationContext, AppDatabase.class, "commons_room.db")
.addMigrations(MIGRATION_1_2)
.fallbackToDestructiveMigration()
.build();
return appDatabase;
}
@Provides
public ContributionDao providesContributionsDao(AppDatabase appDatabase) {
return appDatabase.contributionDao();
}
@Provides
public PlaceDao providesPlaceDao(AppDatabase appDatabase) {
return appDatabase.PlaceDao();
}
/**
* Get the reference of DepictsDao class.
*/
@Provides
public DepictsDao providesDepictDao(AppDatabase appDatabase) {
return appDatabase.DepictsDao();
}
/**
* Get the reference of UploadedStatus class.
*/
@Provides
public UploadedStatusDao providesUploadedStatusDao(AppDatabase appDatabase) {
return appDatabase.UploadedStatusDao();
}
/**
* Get the reference of NotForUploadStatus class.
*/
@Provides
public NotForUploadStatusDao providesNotForUploadStatusDao(AppDatabase appDatabase) {
return appDatabase.NotForUploadStatusDao();
}
/**
* Get the reference of ReviewDao class
*/
@Provides
public ReviewDao providesReviewDao(AppDatabase appDatabase){
return appDatabase.ReviewDao();
}
@Provides
public ContentResolver providesContentResolver(Context context){
return context.getContentResolver();
}
}

View file

@ -0,0 +1,239 @@
package fr.free.nrw.commons.di
import android.app.Activity
import android.content.ContentProviderClient
import android.content.ContentResolver
import android.content.Context
import android.view.inputmethod.InputMethodManager
import androidx.collection.LruCache
import androidx.room.Room.databaseBuilder
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.google.gson.Gson
import dagger.Module
import dagger.Provides
import fr.free.nrw.commons.BuildConfig
import fr.free.nrw.commons.R
import fr.free.nrw.commons.auth.SessionManager
import fr.free.nrw.commons.contributions.ContributionDao
import fr.free.nrw.commons.customselector.database.NotForUploadStatusDao
import fr.free.nrw.commons.customselector.database.UploadedStatusDao
import fr.free.nrw.commons.customselector.ui.selector.ImageFileLoader
import fr.free.nrw.commons.data.DBOpenHelper
import fr.free.nrw.commons.db.AppDatabase
import fr.free.nrw.commons.kvstore.JsonKvStore
import fr.free.nrw.commons.location.LocationServiceManager
import fr.free.nrw.commons.nearby.PlaceDao
import fr.free.nrw.commons.review.ReviewDao
import fr.free.nrw.commons.settings.Prefs
import fr.free.nrw.commons.upload.UploadController
import fr.free.nrw.commons.upload.depicts.DepictsDao
import fr.free.nrw.commons.utils.ConfigUtils.isBetaFlavour
import fr.free.nrw.commons.wikidata.WikidataEditListener
import fr.free.nrw.commons.wikidata.WikidataEditListenerImpl
import io.reactivex.Scheduler
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.util.Objects
import javax.inject.Named
import javax.inject.Singleton
/**
* The Dependency Provider class for Commons Android.
* Provides all sorts of ContentProviderClients used by the app
* along with the Liscences, AccountUtility, UploadController, Logged User,
* Location manager etc
*/
@Module
@Suppress("unused")
open class CommonsApplicationModule(private val applicationContext: Context) {
@Provides
fun providesImageFileLoader(context: Context): ImageFileLoader =
ImageFileLoader(context)
@Provides
fun providesApplicationContext(): Context =
applicationContext
@Provides
fun provideInputMethodManager(): InputMethodManager =
applicationContext.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
@Provides
@Named("licenses")
fun provideLicenses(context: Context): List<String> = listOf(
context.getString(R.string.license_name_cc0),
context.getString(R.string.license_name_cc_by),
context.getString(R.string.license_name_cc_by_sa),
context.getString(R.string.license_name_cc_by_four),
context.getString(R.string.license_name_cc_by_sa_four)
)
@Provides
@Named("licenses_by_name")
fun provideLicensesByName(context: Context): Map<String, String> = mapOf(
context.getString(R.string.license_name_cc0) to Prefs.Licenses.CC0,
context.getString(R.string.license_name_cc_by) to Prefs.Licenses.CC_BY_3,
context.getString(R.string.license_name_cc_by_sa) to Prefs.Licenses.CC_BY_SA_3,
context.getString(R.string.license_name_cc_by_four) to Prefs.Licenses.CC_BY_4,
context.getString(R.string.license_name_cc_by_sa_four) to Prefs.Licenses.CC_BY_SA_4
)
/**
* Provides an instance of CategoryContentProviderClient i.e. the categories
* that are there in local storage
*/
@Provides
@Named("category")
open fun provideCategoryContentProviderClient(context: Context): ContentProviderClient? =
context.contentResolver.acquireContentProviderClient(BuildConfig.CATEGORY_AUTHORITY)
@Provides
@Named("recentsearch")
fun provideRecentSearchContentProviderClient(context: Context): ContentProviderClient? =
context.contentResolver.acquireContentProviderClient(BuildConfig.RECENT_SEARCH_AUTHORITY)
@Provides
@Named("contribution")
open fun provideContributionContentProviderClient(context: Context): ContentProviderClient? =
context.contentResolver.acquireContentProviderClient(BuildConfig.CONTRIBUTION_AUTHORITY)
@Provides
@Named("modification")
open fun provideModificationContentProviderClient(context: Context): ContentProviderClient? =
context.contentResolver.acquireContentProviderClient(BuildConfig.MODIFICATION_AUTHORITY)
@Provides
@Named("bookmarks")
fun provideBookmarkContentProviderClient(context: Context): ContentProviderClient? =
context.contentResolver.acquireContentProviderClient(BuildConfig.BOOKMARK_AUTHORITY)
@Provides
@Named("bookmarksLocation")
fun provideBookmarkLocationContentProviderClient(context: Context): ContentProviderClient? =
context.contentResolver.acquireContentProviderClient(BuildConfig.BOOKMARK_LOCATIONS_AUTHORITY)
@Provides
@Named("bookmarksItem")
fun provideBookmarkItemContentProviderClient(context: Context): ContentProviderClient? =
context.contentResolver.acquireContentProviderClient(BuildConfig.BOOKMARK_ITEMS_AUTHORITY)
/**
* This method is used to provide instance of RecentLanguagesContentProvider
* which provides content of recent used languages from database
* @param context Context
* @return returns RecentLanguagesContentProvider
*/
@Provides
@Named("recent_languages")
fun provideRecentLanguagesContentProviderClient(context: Context): ContentProviderClient? =
context.contentResolver.acquireContentProviderClient(BuildConfig.RECENT_LANGUAGE_AUTHORITY)
/**
* Provides a Json store instance(JsonKvStore) which keeps
* the provided Gson in it's instance
* @param gson stored inside the store instance
*/
@Provides
@Named("default_preferences")
open fun providesDefaultKvStore(context: Context, gson: Gson): JsonKvStore =
JsonKvStore(context, "${context.packageName}_preferences", gson)
@Provides
fun providesUploadController(
sessionManager: SessionManager,
@Named("default_preferences") kvStore: JsonKvStore,
context: Context
): UploadController = UploadController(sessionManager, context, kvStore)
@Provides
@Singleton
open fun provideLocationServiceManager(context: Context): LocationServiceManager =
LocationServiceManager(context)
@Provides
@Singleton
open fun provideDBOpenHelper(context: Context): DBOpenHelper =
DBOpenHelper(context)
@Provides
@Singleton
@Named("thumbnail-cache")
open fun provideLruCache(): LruCache<String, String> =
LruCache(1024)
@Provides
@Singleton
fun provideWikidataEditListener(): WikidataEditListener =
WikidataEditListenerImpl()
@Named("isBeta")
@Provides
@Singleton
fun provideIsBetaVariant(): Boolean =
isBetaFlavour
@Named(IO_THREAD)
@Provides
fun providesIoThread(): Scheduler =
Schedulers.io()
@Named(MAIN_THREAD)
@Provides
fun providesMainThread(): Scheduler =
AndroidSchedulers.mainThread()
@Named("username")
@Provides
fun provideLoggedInUsername(sessionManager: SessionManager): String =
Objects.toString(sessionManager.userName, "")
@Provides
@Singleton
fun provideAppDataBase(): AppDatabase = databaseBuilder(
applicationContext,
AppDatabase::class.java,
"commons_room.db"
).addMigrations(MIGRATION_1_2).fallbackToDestructiveMigration().build()
@Provides
fun providesContributionsDao(appDatabase: AppDatabase): ContributionDao =
appDatabase.contributionDao()
@Provides
fun providesPlaceDao(appDatabase: AppDatabase): PlaceDao =
appDatabase.PlaceDao()
@Provides
fun providesDepictDao(appDatabase: AppDatabase): DepictsDao =
appDatabase.DepictsDao()
@Provides
fun providesUploadedStatusDao(appDatabase: AppDatabase): UploadedStatusDao =
appDatabase.UploadedStatusDao()
@Provides
fun providesNotForUploadStatusDao(appDatabase: AppDatabase): NotForUploadStatusDao =
appDatabase.NotForUploadStatusDao()
@Provides
fun providesReviewDao(appDatabase: AppDatabase): ReviewDao =
appDatabase.ReviewDao()
@Provides
fun providesContentResolver(context: Context): ContentResolver =
context.contentResolver
companion object {
const val IO_THREAD: String = "io_thread"
const val MAIN_THREAD: String = "main_thread"
val MIGRATION_1_2: Migration = object : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL(
"ALTER TABLE contribution " + " ADD COLUMN hasInvalidLocation INTEGER NOT NULL DEFAULT 0"
)
}
}
}
}

View file

@ -37,9 +37,8 @@ class TestCommonsApplication : Application() {
}
@Suppress("MemberVisibilityCanBePrivate")
class MockCommonsApplicationModule(
appContext: Context,
) : CommonsApplicationModule(appContext) {
class MockCommonsApplicationModule(appContext: Context) : CommonsApplicationModule(appContext) {
val defaultSharedPreferences: JsonKvStore = mock()
val locationServiceManager: LocationServiceManager = mock()
val mockDbOpenHelper: DBOpenHelper = mock()
@ -50,16 +49,13 @@ class MockCommonsApplicationModule(
val modificationClient: ContentProviderClient = mock()
val uploadPrefs: JsonKvStore = mock()
override fun provideCategoryContentProviderClient(context: Context?): ContentProviderClient = categoryClient
override fun provideCategoryContentProviderClient(context: Context): ContentProviderClient = categoryClient
override fun provideContributionContentProviderClient(context: Context?): ContentProviderClient = contributionClient
override fun provideContributionContentProviderClient(context: Context): ContentProviderClient = contributionClient
override fun provideModificationContentProviderClient(context: Context?): ContentProviderClient = modificationClient
override fun provideModificationContentProviderClient(context: Context): ContentProviderClient = modificationClient
override fun providesDefaultKvStore(
context: Context,
gson: Gson,
): JsonKvStore = defaultSharedPreferences
override fun providesDefaultKvStore(context: Context, gson: Gson): JsonKvStore = defaultSharedPreferences
override fun provideLocationServiceManager(context: Context): LocationServiceManager = locationServiceManager