Convert dependency inject ("di") package to kotlin (#5976)

* Convert a batch of easier modules

* Convert the NetworkingModule to kotlin

* Converted the ApplicationlessInjection to kotlin

* Convert CommonsDaggerAppCompatActivity to kotlin

* Convert CommonsDaggerContentProvider to kotlin

* Convert CommonsDaggerIntentService to kotlin

* Convert CommonsDaggerService to kotlin

* Convert CommonsDaggerSupportFragment to kotlin

* Convert CommonsDaggerBroadcastReceiver to kotlin

* Convert CommonsApplicationModule to kotlin

* Fix imports and make them consistent
This commit is contained in:
Paul Hawke 2024-11-29 19:50:42 -06:00 committed by GitHub
parent dac3657536
commit 1e5521b434
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
41 changed files with 1274 additions and 1465 deletions

View file

@ -3,7 +3,7 @@ package fr.free.nrw.commons.actions
import fr.free.nrw.commons.CommonsApplication
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException
import fr.free.nrw.commons.di.NetworkingModule.NAMED_COMMONS_CSRF
import fr.free.nrw.commons.di.NetworkingModule.Companion.NAMED_COMMONS_CSRF
import io.reactivex.Observable
import javax.inject.Inject
import javax.inject.Named

View file

@ -3,9 +3,8 @@ package fr.free.nrw.commons.campaigns
import android.annotation.SuppressLint
import fr.free.nrw.commons.BasePresenter
import fr.free.nrw.commons.campaigns.models.Campaign
import fr.free.nrw.commons.di.CommonsApplicationModule
import fr.free.nrw.commons.di.CommonsApplicationModule.IO_THREAD
import fr.free.nrw.commons.di.CommonsApplicationModule.MAIN_THREAD
import fr.free.nrw.commons.di.CommonsApplicationModule.Companion.IO_THREAD
import fr.free.nrw.commons.di.CommonsApplicationModule.Companion.MAIN_THREAD
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient
import fr.free.nrw.commons.utils.CommonsDateUtil.getIso8601DateFormatShort
import io.reactivex.Scheduler

View file

@ -3,6 +3,7 @@ package fr.free.nrw.commons.contributions
import androidx.paging.PagedList.BoundaryCallback
import fr.free.nrw.commons.auth.SessionManager
import fr.free.nrw.commons.di.CommonsApplicationModule
import fr.free.nrw.commons.di.CommonsApplicationModule.Companion.IO_THREAD
import fr.free.nrw.commons.media.MediaClient
import io.reactivex.Scheduler
import io.reactivex.disposables.CompositeDisposable
@ -20,7 +21,7 @@ class ContributionBoundaryCallback
private val repository: ContributionsRepository,
private val sessionManager: SessionManager,
private val mediaClient: MediaClient,
@param:Named(CommonsApplicationModule.IO_THREAD) private val ioThreadScheduler: Scheduler,
@param:Named(IO_THREAD) private val ioThreadScheduler: Scheduler,
) : BoundaryCallback<Contribution>() {
private val compositeDisposable: CompositeDisposable = CompositeDisposable()
var userName: String? = null

View file

@ -1,5 +1,7 @@
package fr.free.nrw.commons.contributions;
import static fr.free.nrw.commons.di.CommonsApplicationModule.IO_THREAD;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.paging.DataSource;
@ -34,7 +36,7 @@ public class ContributionsListPresenter implements UserActionListener {
final ContributionBoundaryCallback contributionBoundaryCallback,
final ContributionsRemoteDataSource contributionsRemoteDataSource,
final ContributionsRepository repository,
@Named(CommonsApplicationModule.IO_THREAD) final Scheduler ioThreadScheduler) {
@Named(IO_THREAD) final Scheduler ioThreadScheduler) {
this.contributionBoundaryCallback = contributionBoundaryCallback;
this.repository = repository;
this.ioThreadScheduler = ioThreadScheduler;

View file

@ -1,5 +1,6 @@
package fr.free.nrw.commons.contributions;
import static fr.free.nrw.commons.di.CommonsApplicationModule.IO_THREAD;
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK;
import androidx.work.ExistingWorkPolicy;
@ -31,7 +32,7 @@ public class ContributionsPresenter implements UserActionListener {
@Inject
ContributionsPresenter(ContributionsRepository repository,
UploadRepository uploadRepository,
@Named(CommonsApplicationModule.IO_THREAD) Scheduler ioThreadScheduler) {
@Named(IO_THREAD) Scheduler ioThreadScheduler) {
this.contributionsRepository = repository;
this.uploadRepository = uploadRepository;
this.ioThreadScheduler = ioThreadScheduler;

View file

@ -1,7 +1,7 @@
package fr.free.nrw.commons.contributions
import androidx.paging.ItemKeyedDataSource
import fr.free.nrw.commons.di.CommonsApplicationModule
import fr.free.nrw.commons.di.CommonsApplicationModule.Companion.IO_THREAD
import fr.free.nrw.commons.media.MediaClient
import io.reactivex.Scheduler
import io.reactivex.disposables.CompositeDisposable
@ -16,7 +16,7 @@ class ContributionsRemoteDataSource
@Inject
constructor(
private val mediaClient: MediaClient,
@param:Named(CommonsApplicationModule.IO_THREAD) private val ioThreadScheduler: Scheduler,
@param:Named(IO_THREAD) private val ioThreadScheduler: Scheduler,
) : ItemKeyedDataSource<Int, Contribution>() {
private val compositeDisposable: CompositeDisposable = CompositeDisposable()
var userName: String? = null

View file

@ -22,7 +22,10 @@ import java.util.Map;
public class Converters {
public static Gson getGson() {
return ApplicationlessInjection.getInstance(CommonsApplication.getInstance()).getCommonsApplicationComponent().gson();
return ApplicationlessInjection
.getInstance(CommonsApplication.getInstance())
.getCommonsApplicationComponent()
.gson();
}
/**

View file

@ -1,90 +0,0 @@
package fr.free.nrw.commons.di;
import dagger.Module;
import dagger.android.ContributesAndroidInjector;
import fr.free.nrw.commons.AboutActivity;
import fr.free.nrw.commons.LocationPicker.LocationPickerActivity;
import fr.free.nrw.commons.WelcomeActivity;
import fr.free.nrw.commons.auth.LoginActivity;
import fr.free.nrw.commons.auth.SignupActivity;
import fr.free.nrw.commons.category.CategoryDetailsActivity;
import fr.free.nrw.commons.contributions.MainActivity;
import fr.free.nrw.commons.customselector.ui.selector.CustomSelectorActivity;
import fr.free.nrw.commons.description.DescriptionEditActivity;
import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity;
import fr.free.nrw.commons.explore.SearchActivity;
import fr.free.nrw.commons.media.ZoomableActivity;
import fr.free.nrw.commons.nearby.WikidataFeedback;
import fr.free.nrw.commons.notification.NotificationActivity;
import fr.free.nrw.commons.profile.ProfileActivity;
import fr.free.nrw.commons.review.ReviewActivity;
import fr.free.nrw.commons.settings.SettingsActivity;
import fr.free.nrw.commons.upload.UploadActivity;
import fr.free.nrw.commons.upload.UploadProgressActivity;
/**
* This Class handles the dependency injection (using dagger)
* so, if a developer needs to add a new activity to the commons app
* then that must be mentioned here to inject the dependencies
*/
@Module
@SuppressWarnings({"WeakerAccess", "unused"})
public abstract class ActivityBuilderModule {
@ContributesAndroidInjector
abstract LoginActivity bindLoginActivity();
@ContributesAndroidInjector
abstract WelcomeActivity bindWelcomeActivity();
@ContributesAndroidInjector
abstract MainActivity bindContributionsActivity();
@ContributesAndroidInjector
abstract CustomSelectorActivity bindCustomSelectorActivity();
@ContributesAndroidInjector
abstract SettingsActivity bindSettingsActivity();
@ContributesAndroidInjector
abstract AboutActivity bindAboutActivity();
@ContributesAndroidInjector
abstract LocationPickerActivity bindLocationPickerActivity();
@ContributesAndroidInjector
abstract SignupActivity bindSignupActivity();
@ContributesAndroidInjector
abstract NotificationActivity bindNotificationActivity();
@ContributesAndroidInjector
abstract UploadActivity bindUploadActivity();
@ContributesAndroidInjector
abstract SearchActivity bindSearchActivity();
@ContributesAndroidInjector
abstract CategoryDetailsActivity bindCategoryDetailsActivity();
@ContributesAndroidInjector
abstract WikidataItemDetailsActivity bindDepictionDetailsActivity();
@ContributesAndroidInjector
abstract ProfileActivity bindAchievementsActivity();
@ContributesAndroidInjector
abstract ReviewActivity bindReviewActivity();
@ContributesAndroidInjector
abstract DescriptionEditActivity bindDescriptionEditActivity();
@ContributesAndroidInjector
abstract ZoomableActivity bindZoomableActivity();
@ContributesAndroidInjector
abstract UploadProgressActivity bindUploadProgressActivity();
@ContributesAndroidInjector
abstract WikidataFeedback bindWikiFeedback();
}

View file

@ -0,0 +1,89 @@
package fr.free.nrw.commons.di
import dagger.Module
import dagger.android.ContributesAndroidInjector
import fr.free.nrw.commons.AboutActivity
import fr.free.nrw.commons.LocationPicker.LocationPickerActivity
import fr.free.nrw.commons.WelcomeActivity
import fr.free.nrw.commons.auth.LoginActivity
import fr.free.nrw.commons.auth.SignupActivity
import fr.free.nrw.commons.category.CategoryDetailsActivity
import fr.free.nrw.commons.contributions.MainActivity
import fr.free.nrw.commons.customselector.ui.selector.CustomSelectorActivity
import fr.free.nrw.commons.description.DescriptionEditActivity
import fr.free.nrw.commons.explore.SearchActivity
import fr.free.nrw.commons.explore.depictions.WikidataItemDetailsActivity
import fr.free.nrw.commons.media.ZoomableActivity
import fr.free.nrw.commons.nearby.WikidataFeedback
import fr.free.nrw.commons.notification.NotificationActivity
import fr.free.nrw.commons.profile.ProfileActivity
import fr.free.nrw.commons.review.ReviewActivity
import fr.free.nrw.commons.settings.SettingsActivity
import fr.free.nrw.commons.upload.UploadActivity
import fr.free.nrw.commons.upload.UploadProgressActivity
/**
* This Class handles the dependency injection (using dagger)
* so, if a developer needs to add a new activity to the commons app
* then that must be mentioned here to inject the dependencies
*/
@Module
@Suppress("unused")
abstract class ActivityBuilderModule {
@ContributesAndroidInjector
abstract fun bindLoginActivity(): LoginActivity
@ContributesAndroidInjector
abstract fun bindWelcomeActivity(): WelcomeActivity
@ContributesAndroidInjector
abstract fun bindContributionsActivity(): MainActivity
@ContributesAndroidInjector
abstract fun bindCustomSelectorActivity(): CustomSelectorActivity
@ContributesAndroidInjector
abstract fun bindSettingsActivity(): SettingsActivity
@ContributesAndroidInjector
abstract fun bindAboutActivity(): AboutActivity
@ContributesAndroidInjector
abstract fun bindLocationPickerActivity(): LocationPickerActivity
@ContributesAndroidInjector
abstract fun bindSignupActivity(): SignupActivity
@ContributesAndroidInjector
abstract fun bindNotificationActivity(): NotificationActivity
@ContributesAndroidInjector
abstract fun bindUploadActivity(): UploadActivity
@ContributesAndroidInjector
abstract fun bindSearchActivity(): SearchActivity
@ContributesAndroidInjector
abstract fun bindCategoryDetailsActivity(): CategoryDetailsActivity
@ContributesAndroidInjector
abstract fun bindDepictionDetailsActivity(): WikidataItemDetailsActivity
@ContributesAndroidInjector
abstract fun bindAchievementsActivity(): ProfileActivity
@ContributesAndroidInjector
abstract fun bindReviewActivity(): ReviewActivity
@ContributesAndroidInjector
abstract fun bindDescriptionEditActivity(): DescriptionEditActivity
@ContributesAndroidInjector
abstract fun bindZoomableActivity(): ZoomableActivity
@ContributesAndroidInjector
abstract fun bindUploadProgressActivity(): UploadProgressActivity
@ContributesAndroidInjector
abstract fun bindWikiFeedback(): WikidataFeedback
}

View file

@ -1,105 +0,0 @@
package fr.free.nrw.commons.di;
import android.app.Activity;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentProvider;
import android.content.Context;
import androidx.fragment.app.Fragment;
import dagger.android.HasAndroidInjector;
import javax.inject.Inject;
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
import dagger.android.HasActivityInjector;
import dagger.android.HasBroadcastReceiverInjector;
import dagger.android.HasContentProviderInjector;
import dagger.android.HasFragmentInjector;
import dagger.android.HasServiceInjector;
import dagger.android.support.HasSupportFragmentInjector;
/**
* Provides injectors for all sorts of components
* Ex: Activities, Fragments, Services, ContentProviders
*/
public class ApplicationlessInjection
implements
HasAndroidInjector,
HasActivityInjector,
HasFragmentInjector,
HasSupportFragmentInjector,
HasServiceInjector,
HasBroadcastReceiverInjector,
HasContentProviderInjector {
private static ApplicationlessInjection instance = null;
@Inject DispatchingAndroidInjector<Object> androidInjector;
@Inject DispatchingAndroidInjector<Activity> activityInjector;
@Inject DispatchingAndroidInjector<BroadcastReceiver> broadcastReceiverInjector;
@Inject DispatchingAndroidInjector<android.app.Fragment> fragmentInjector;
@Inject DispatchingAndroidInjector<Fragment> supportFragmentInjector;
@Inject DispatchingAndroidInjector<Service> serviceInjector;
@Inject DispatchingAndroidInjector<ContentProvider> contentProviderInjector;
private CommonsApplicationComponent commonsApplicationComponent;
public ApplicationlessInjection(Context applicationContext) {
commonsApplicationComponent = DaggerCommonsApplicationComponent.builder()
.appModule(new CommonsApplicationModule(applicationContext)).build();
commonsApplicationComponent.inject(this);
}
@Override
public AndroidInjector<Object> androidInjector() {
return androidInjector;
}
@Override
public DispatchingAndroidInjector<Activity> activityInjector() {
return activityInjector;
}
@Override
public DispatchingAndroidInjector<android.app.Fragment> fragmentInjector() {
return fragmentInjector;
}
@Override
public DispatchingAndroidInjector<Fragment> supportFragmentInjector() {
return supportFragmentInjector;
}
@Override
public DispatchingAndroidInjector<BroadcastReceiver> broadcastReceiverInjector() {
return broadcastReceiverInjector;
}
@Override
public DispatchingAndroidInjector<Service> serviceInjector() {
return serviceInjector;
}
@Override
public AndroidInjector<ContentProvider> contentProviderInjector() {
return contentProviderInjector;
}
public CommonsApplicationComponent getCommonsApplicationComponent() {
return commonsApplicationComponent;
}
public static ApplicationlessInjection getInstance(Context applicationContext) {
if (instance == null) {
synchronized (ApplicationlessInjection.class) {
if (instance == null) {
instance = new ApplicationlessInjection(applicationContext);
}
}
}
return instance;
}
}

View file

@ -0,0 +1,98 @@
package fr.free.nrw.commons.di
import android.app.Activity
import android.app.Fragment
import android.app.Service
import android.content.BroadcastReceiver
import android.content.ContentProvider
import android.content.Context
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasActivityInjector
import dagger.android.HasAndroidInjector
import dagger.android.HasBroadcastReceiverInjector
import dagger.android.HasContentProviderInjector
import dagger.android.HasFragmentInjector
import dagger.android.HasServiceInjector
import dagger.android.support.HasSupportFragmentInjector
import javax.inject.Inject
import androidx.fragment.app.Fragment as AndroidXFragmen
/**
* Provides injectors for all sorts of components
* Ex: Activities, Fragments, Services, ContentProviders
*/
class ApplicationlessInjection(applicationContext: Context) : HasAndroidInjector,
HasActivityInjector, HasFragmentInjector, HasSupportFragmentInjector, HasServiceInjector,
HasBroadcastReceiverInjector, HasContentProviderInjector {
@Inject @JvmField
var androidInjector: DispatchingAndroidInjector<Any>? = null
@Inject @JvmField
var activityInjector: DispatchingAndroidInjector<Activity>? = null
@Inject @JvmField
var broadcastReceiverInjector: DispatchingAndroidInjector<BroadcastReceiver>? = null
@Inject @JvmField
var fragmentInjector: DispatchingAndroidInjector<Fragment>? = null
@Inject @JvmField
var supportFragmentInjector: DispatchingAndroidInjector<AndroidXFragmen>? = null
@Inject @JvmField
var serviceInjector: DispatchingAndroidInjector<Service>? = null
@Inject @JvmField
var contentProviderInjector: DispatchingAndroidInjector<ContentProvider>? = null
val instance: ApplicationlessInjection get() = _instance!!
val commonsApplicationComponent: CommonsApplicationComponent =
DaggerCommonsApplicationComponent
.builder()
.appModule(CommonsApplicationModule(applicationContext))
.build()
init {
commonsApplicationComponent.inject(this)
}
override fun androidInjector(): AndroidInjector<Any>? =
androidInjector
override fun activityInjector(): DispatchingAndroidInjector<Activity>? =
activityInjector
override fun fragmentInjector(): DispatchingAndroidInjector<Fragment>? =
fragmentInjector
override fun supportFragmentInjector(): DispatchingAndroidInjector<AndroidXFragmen>? =
supportFragmentInjector
override fun broadcastReceiverInjector(): DispatchingAndroidInjector<BroadcastReceiver>? =
broadcastReceiverInjector
override fun serviceInjector(): DispatchingAndroidInjector<Service>? =
serviceInjector
override fun contentProviderInjector(): AndroidInjector<ContentProvider>? =
contentProviderInjector
companion object {
private var _instance: ApplicationlessInjection? = null
@JvmStatic
fun getInstance(applicationContext: Context): ApplicationlessInjection {
if (_instance == null) {
synchronized(ApplicationlessInjection::class.java) {
if (_instance == null) {
_instance = ApplicationlessInjection(applicationContext)
}
}
}
return _instance!!
}
}
}

View file

@ -1,85 +0,0 @@
package fr.free.nrw.commons.di;
import com.google.gson.Gson;
import fr.free.nrw.commons.explore.categories.CategoriesModule;
import fr.free.nrw.commons.navtab.MoreBottomSheetFragment;
import fr.free.nrw.commons.navtab.MoreBottomSheetLoggedOutFragment;
import fr.free.nrw.commons.nearby.NearbyController;
import fr.free.nrw.commons.upload.worker.UploadWorker;
import javax.inject.Singleton;
import dagger.Component;
import dagger.android.AndroidInjectionModule;
import dagger.android.AndroidInjector;
import dagger.android.support.AndroidSupportInjectionModule;
import fr.free.nrw.commons.CommonsApplication;
import fr.free.nrw.commons.auth.LoginActivity;
import fr.free.nrw.commons.contributions.ContributionsModule;
import fr.free.nrw.commons.explore.depictions.DepictionModule;
import fr.free.nrw.commons.explore.SearchModule;
import fr.free.nrw.commons.review.ReviewController;
import fr.free.nrw.commons.settings.SettingsFragment;
import fr.free.nrw.commons.upload.FileProcessor;
import fr.free.nrw.commons.upload.UploadModule;
import fr.free.nrw.commons.widget.PicOfDayAppWidget;
/**
* Facilitates Injection from CommonsApplicationModule to all the
* classes seeking a dependency to be injected
*/
@Singleton
@Component(modules = {
CommonsApplicationModule.class,
NetworkingModule.class,
AndroidInjectionModule.class,
AndroidSupportInjectionModule.class,
ActivityBuilderModule.class,
FragmentBuilderModule.class,
ServiceBuilderModule.class,
ContentProviderBuilderModule.class,
UploadModule.class,
ContributionsModule.class,
SearchModule.class,
DepictionModule.class,
CategoriesModule.class
})
public interface CommonsApplicationComponent extends AndroidInjector<ApplicationlessInjection> {
void inject(CommonsApplication application);
void inject(UploadWorker worker);
void inject(LoginActivity activity);
void inject(SettingsFragment fragment);
void inject(MoreBottomSheetFragment fragment);
void inject(MoreBottomSheetLoggedOutFragment fragment);
void inject(ReviewController reviewController);
//void inject(NavTabLayout view);
@Override
void inject(ApplicationlessInjection instance);
void inject(FileProcessor fileProcessor);
void inject(PicOfDayAppWidget picOfDayAppWidget);
@Singleton
void inject(NearbyController nearbyController);
Gson gson();
@Component.Builder
@SuppressWarnings({"WeakerAccess", "unused"})
interface Builder {
Builder appModule(CommonsApplicationModule applicationModule);
CommonsApplicationComponent build();
}
}

View file

@ -0,0 +1,80 @@
package fr.free.nrw.commons.di
import com.google.gson.Gson
import dagger.Component
import dagger.android.AndroidInjectionModule
import dagger.android.AndroidInjector
import dagger.android.support.AndroidSupportInjectionModule
import fr.free.nrw.commons.CommonsApplication
import fr.free.nrw.commons.auth.LoginActivity
import fr.free.nrw.commons.contributions.ContributionsModule
import fr.free.nrw.commons.explore.SearchModule
import fr.free.nrw.commons.explore.categories.CategoriesModule
import fr.free.nrw.commons.explore.depictions.DepictionModule
import fr.free.nrw.commons.navtab.MoreBottomSheetFragment
import fr.free.nrw.commons.navtab.MoreBottomSheetLoggedOutFragment
import fr.free.nrw.commons.nearby.NearbyController
import fr.free.nrw.commons.review.ReviewController
import fr.free.nrw.commons.settings.SettingsFragment
import fr.free.nrw.commons.upload.FileProcessor
import fr.free.nrw.commons.upload.UploadModule
import fr.free.nrw.commons.upload.worker.UploadWorker
import fr.free.nrw.commons.widget.PicOfDayAppWidget
import javax.inject.Singleton
/**
* Facilitates Injection from CommonsApplicationModule to all the
* classes seeking a dependency to be injected
*/
@Singleton
@Component(
modules = [
CommonsApplicationModule::class,
NetworkingModule::class,
AndroidInjectionModule::class,
AndroidSupportInjectionModule::class,
ActivityBuilderModule::class,
FragmentBuilderModule::class,
ServiceBuilderModule::class,
ContentProviderBuilderModule::class,
UploadModule::class,
ContributionsModule::class,
SearchModule::class,
DepictionModule::class,
CategoriesModule::class
]
)
interface CommonsApplicationComponent : AndroidInjector<ApplicationlessInjection> {
fun inject(application: CommonsApplication)
fun inject(worker: UploadWorker)
fun inject(activity: LoginActivity)
fun inject(fragment: SettingsFragment)
fun inject(fragment: MoreBottomSheetFragment)
fun inject(fragment: MoreBottomSheetLoggedOutFragment)
fun inject(reviewController: ReviewController)
override fun inject(instance: ApplicationlessInjection)
fun inject(fileProcessor: FileProcessor)
fun inject(picOfDayAppWidget: PicOfDayAppWidget)
@Singleton
fun inject(nearbyController: NearbyController)
fun gson(): Gson
@Component.Builder
@Suppress("unused")
interface Builder {
fun appModule(applicationModule: CommonsApplicationModule): Builder
fun build(): CommonsApplicationComponent
}
}

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

@ -1,48 +0,0 @@
package fr.free.nrw.commons.di;
import android.app.Activity;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import javax.inject.Inject;
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
import dagger.android.support.HasSupportFragmentInjector;
public abstract class CommonsDaggerAppCompatActivity extends AppCompatActivity implements HasSupportFragmentInjector {
@Inject
DispatchingAndroidInjector<Fragment> supportFragmentInjector;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
inject();
super.onCreate(savedInstanceState);
}
@Override
public AndroidInjector<Fragment> supportFragmentInjector() {
return supportFragmentInjector;
}
/**
* when this Activity is created it injects an instance of this class inside
* activityInjector method of ApplicationlessInjection
*/
private void inject() {
ApplicationlessInjection injection = ApplicationlessInjection.getInstance(getApplicationContext());
AndroidInjector<Activity> activityInjector = injection.activityInjector();
if (activityInjector == null) {
throw new NullPointerException("ApplicationlessInjection.activityInjector() returned null");
}
activityInjector.inject(this);
}
}

View file

@ -0,0 +1,37 @@
package fr.free.nrw.commons.di
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.support.HasSupportFragmentInjector
import fr.free.nrw.commons.di.ApplicationlessInjection.Companion.getInstance
import javax.inject.Inject
abstract class CommonsDaggerAppCompatActivity : AppCompatActivity(), HasSupportFragmentInjector {
@Inject @JvmField
var supportFragmentInjector: DispatchingAndroidInjector<Fragment>? = null
override fun onCreate(savedInstanceState: Bundle?) {
inject()
super.onCreate(savedInstanceState)
}
override fun supportFragmentInjector(): AndroidInjector<Fragment> {
return supportFragmentInjector!!
}
/**
* when this Activity is created it injects an instance of this class inside
* activityInjector method of ApplicationlessInjection
*/
private fun inject() {
val injection = getInstance(applicationContext)
val activityInjector = injection.activityInjector()
?: throw NullPointerException("ApplicationlessInjection.activityInjector() returned null")
activityInjector.inject(this)
}
}

View file

@ -1,35 +0,0 @@
package fr.free.nrw.commons.di;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import dagger.android.AndroidInjector;
/**
* Receives broadcast then injects it's instance to the broadcastReceiverInjector method of
* ApplicationlessInjection class
*/
public abstract class CommonsDaggerBroadcastReceiver extends BroadcastReceiver {
public CommonsDaggerBroadcastReceiver() {
super();
}
@Override
public void onReceive(Context context, Intent intent) {
inject(context);
}
private void inject(Context context) {
ApplicationlessInjection injection = ApplicationlessInjection.getInstance(context.getApplicationContext());
AndroidInjector<BroadcastReceiver> serviceInjector = injection.broadcastReceiverInjector();
if (serviceInjector == null) {
throw new NullPointerException("ApplicationlessInjection.broadcastReceiverInjector() returned null");
}
serviceInjector.inject(this);
}
}

View file

@ -0,0 +1,25 @@
package fr.free.nrw.commons.di
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import fr.free.nrw.commons.di.ApplicationlessInjection.Companion.getInstance
/**
* Receives broadcast then injects it's instance to the broadcastReceiverInjector method of
* ApplicationlessInjection class
*/
abstract class CommonsDaggerBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
inject(context)
}
private fun inject(context: Context) {
val injection = getInstance(context.applicationContext)
val serviceInjector = injection.broadcastReceiverInjector()
?: throw NullPointerException("ApplicationlessInjection.broadcastReceiverInjector() returned null")
serviceInjector.inject(this)
}
}

View file

@ -1,32 +0,0 @@
package fr.free.nrw.commons.di;
import android.content.ContentProvider;
import dagger.android.AndroidInjector;
public abstract class CommonsDaggerContentProvider extends ContentProvider {
public CommonsDaggerContentProvider() {
super();
}
@Override
public boolean onCreate() {
inject();
return true;
}
private void inject() {
ApplicationlessInjection injection = ApplicationlessInjection.getInstance(getContext());
AndroidInjector<ContentProvider> serviceInjector = injection.contentProviderInjector();
if (serviceInjector == null) {
throw new NullPointerException("ApplicationlessInjection.contentProviderInjector() returned null");
}
serviceInjector.inject(this);
}
}

View file

@ -0,0 +1,20 @@
package fr.free.nrw.commons.di
import android.content.ContentProvider
import fr.free.nrw.commons.di.ApplicationlessInjection.Companion.getInstance
abstract class CommonsDaggerContentProvider : ContentProvider() {
override fun onCreate(): Boolean {
inject()
return true
}
private fun inject() {
val injection = getInstance(context!!)
val serviceInjector = injection.contentProviderInjector()
?: throw NullPointerException("ApplicationlessInjection.contentProviderInjector() returned null")
serviceInjector.inject(this)
}
}

View file

@ -1,32 +0,0 @@
package fr.free.nrw.commons.di;
import android.app.IntentService;
import android.app.Service;
import dagger.android.AndroidInjector;
public abstract class CommonsDaggerIntentService extends IntentService {
public CommonsDaggerIntentService(String name) {
super(name);
}
@Override
public void onCreate() {
inject();
super.onCreate();
}
private void inject() {
ApplicationlessInjection injection = ApplicationlessInjection.getInstance(getApplicationContext());
AndroidInjector<Service> serviceInjector = injection.serviceInjector();
if (serviceInjector == null) {
throw new NullPointerException("ApplicationlessInjection.serviceInjector() returned null");
}
serviceInjector.inject(this);
}
}

View file

@ -0,0 +1,20 @@
package fr.free.nrw.commons.di
import android.app.IntentService
import fr.free.nrw.commons.di.ApplicationlessInjection.Companion.getInstance
abstract class CommonsDaggerIntentService(name: String?) : IntentService(name) {
override fun onCreate() {
inject()
super.onCreate()
}
private fun inject() {
val injection = getInstance(applicationContext)
val serviceInjector = injection.serviceInjector()
?: throw NullPointerException("ApplicationlessInjection.serviceInjector() returned null")
serviceInjector.inject(this)
}
}

View file

@ -1,31 +0,0 @@
package fr.free.nrw.commons.di;
import android.app.Service;
import dagger.android.AndroidInjector;
public abstract class CommonsDaggerService extends Service {
public CommonsDaggerService() {
super();
}
@Override
public void onCreate() {
inject();
super.onCreate();
}
private void inject() {
ApplicationlessInjection injection = ApplicationlessInjection.getInstance(getApplicationContext());
AndroidInjector<Service> serviceInjector = injection.serviceInjector();
if (serviceInjector == null) {
throw new NullPointerException("ApplicationlessInjection.serviceInjector() returned null");
}
serviceInjector.inject(this);
}
}

View file

@ -0,0 +1,20 @@
package fr.free.nrw.commons.di
import android.app.Service
import fr.free.nrw.commons.di.ApplicationlessInjection.Companion.getInstance
abstract class CommonsDaggerService : Service() {
override fun onCreate() {
inject()
super.onCreate()
}
private fun inject() {
val injection = getInstance(applicationContext)
val serviceInjector = injection.serviceInjector()
?: throw NullPointerException("ApplicationlessInjection.serviceInjector() returned null")
serviceInjector.inject(this)
}
}

View file

@ -1,75 +0,0 @@
package fr.free.nrw.commons.di;
import android.app.Activity;
import android.content.Context;
import androidx.fragment.app.Fragment;
import javax.inject.Inject;
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
import dagger.android.support.HasSupportFragmentInjector;
import io.reactivex.disposables.CompositeDisposable;
public abstract class CommonsDaggerSupportFragment extends Fragment implements HasSupportFragmentInjector {
@Inject
DispatchingAndroidInjector<Fragment> childFragmentInjector;
protected CompositeDisposable compositeDisposable = new CompositeDisposable();
@Override
public void onAttach(Context context) {
inject();
super.onAttach(context);
}
@Override
public void onDestroy() {
super.onDestroy();
compositeDisposable.clear();
}
@Override
public AndroidInjector<Fragment> supportFragmentInjector() {
return childFragmentInjector;
}
public void inject() {
HasSupportFragmentInjector hasSupportFragmentInjector = findHasFragmentInjector();
AndroidInjector<Fragment> fragmentInjector = hasSupportFragmentInjector.supportFragmentInjector();
if (fragmentInjector == null) {
throw new NullPointerException(String.format("%s.supportFragmentInjector() returned null", hasSupportFragmentInjector.getClass().getCanonicalName()));
}
fragmentInjector.inject(this);
}
private HasSupportFragmentInjector findHasFragmentInjector() {
Fragment parentFragment = this;
while ((parentFragment = parentFragment.getParentFragment()) != null) {
if (parentFragment instanceof HasSupportFragmentInjector) {
return (HasSupportFragmentInjector) parentFragment;
}
}
Activity activity = getActivity();
if (activity instanceof HasSupportFragmentInjector) {
return (HasSupportFragmentInjector) activity;
}
ApplicationlessInjection injection = ApplicationlessInjection.getInstance(activity.getApplicationContext());
if (injection != null) {
return injection;
}
throw new IllegalArgumentException(String.format("No injector was found for %s", getClass().getCanonicalName()));
}
}

View file

@ -0,0 +1,66 @@
package fr.free.nrw.commons.di
import android.app.Activity
import android.content.Context
import androidx.fragment.app.Fragment
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.support.HasSupportFragmentInjector
import fr.free.nrw.commons.di.ApplicationlessInjection.Companion.getInstance
import io.reactivex.disposables.CompositeDisposable
import javax.inject.Inject
abstract class CommonsDaggerSupportFragment : Fragment(), HasSupportFragmentInjector {
@Inject @JvmField
var childFragmentInjector: DispatchingAndroidInjector<Fragment>? = null
@JvmField
protected var compositeDisposable: CompositeDisposable = CompositeDisposable()
override fun onAttach(context: Context) {
inject()
super.onAttach(context)
}
override fun onDestroy() {
super.onDestroy()
compositeDisposable.clear()
}
override fun supportFragmentInjector(): AndroidInjector<Fragment> =
childFragmentInjector!!
fun inject() {
val hasSupportFragmentInjector = findHasFragmentInjector()
val fragmentInjector = hasSupportFragmentInjector.supportFragmentInjector()
?: throw NullPointerException(
String.format(
"%s.supportFragmentInjector() returned null",
hasSupportFragmentInjector.javaClass.canonicalName
)
)
fragmentInjector.inject(this)
}
private fun findHasFragmentInjector(): HasSupportFragmentInjector {
var parentFragment: Fragment? = this
while ((parentFragment!!.parentFragment.also { parentFragment = it }) != null) {
if (parentFragment is HasSupportFragmentInjector) {
return parentFragment as HasSupportFragmentInjector
}
}
val activity: Activity = requireActivity()
if (activity is HasSupportFragmentInjector) {
return activity
}
return getInstance(activity.applicationContext)
}
}

View file

@ -1,38 +0,0 @@
package fr.free.nrw.commons.di;
import dagger.Module;
import dagger.android.ContributesAndroidInjector;
import fr.free.nrw.commons.bookmarks.items.BookmarkItemsContentProvider;
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsContentProvider;
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesContentProvider;
import fr.free.nrw.commons.category.CategoryContentProvider;
import fr.free.nrw.commons.explore.recentsearches.RecentSearchesContentProvider;
import fr.free.nrw.commons.recentlanguages.RecentLanguagesContentProvider;
/**
* This Class Represents the Module for dependency injection (using dagger)
* so, if a developer needs to add a new ContentProvider to the commons app
* then that must be mentioned here to inject the dependencies
*/
@Module
@SuppressWarnings({ "WeakerAccess", "unused" })
public abstract class ContentProviderBuilderModule {
@ContributesAndroidInjector
abstract CategoryContentProvider bindCategoryContentProvider();
@ContributesAndroidInjector
abstract RecentSearchesContentProvider bindRecentSearchesContentProvider();
@ContributesAndroidInjector
abstract BookmarkPicturesContentProvider bindBookmarkContentProvider();
@ContributesAndroidInjector
abstract BookmarkLocationsContentProvider bindBookmarkLocationContentProvider();
@ContributesAndroidInjector
abstract BookmarkItemsContentProvider bindBookmarkItemContentProvider();
@ContributesAndroidInjector
abstract RecentLanguagesContentProvider bindRecentLanguagesContentProvider();
}

View file

@ -0,0 +1,37 @@
package fr.free.nrw.commons.di
import dagger.Module
import dagger.android.ContributesAndroidInjector
import fr.free.nrw.commons.bookmarks.items.BookmarkItemsContentProvider
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsContentProvider
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesContentProvider
import fr.free.nrw.commons.category.CategoryContentProvider
import fr.free.nrw.commons.explore.recentsearches.RecentSearchesContentProvider
import fr.free.nrw.commons.recentlanguages.RecentLanguagesContentProvider
/**
* This Class Represents the Module for dependency injection (using dagger)
* so, if a developer needs to add a new ContentProvider to the commons app
* then that must be mentioned here to inject the dependencies
*/
@Module
@Suppress("unused")
abstract class ContentProviderBuilderModule {
@ContributesAndroidInjector
abstract fun bindCategoryContentProvider(): CategoryContentProvider
@ContributesAndroidInjector
abstract fun bindRecentSearchesContentProvider(): RecentSearchesContentProvider
@ContributesAndroidInjector
abstract fun bindBookmarkContentProvider(): BookmarkPicturesContentProvider
@ContributesAndroidInjector
abstract fun bindBookmarkLocationContentProvider(): BookmarkLocationsContentProvider
@ContributesAndroidInjector
abstract fun bindBookmarkItemContentProvider(): BookmarkItemsContentProvider
@ContributesAndroidInjector
abstract fun bindRecentLanguagesContentProvider(): RecentLanguagesContentProvider
}

View file

@ -1,166 +0,0 @@
package fr.free.nrw.commons.di;
import dagger.Module;
import dagger.android.ContributesAndroidInjector;
import fr.free.nrw.commons.bookmarks.BookmarkFragment;
import fr.free.nrw.commons.bookmarks.BookmarkListRootFragment;
import fr.free.nrw.commons.bookmarks.items.BookmarkItemsFragment;
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsFragment;
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesFragment;
import fr.free.nrw.commons.contributions.ContributionsFragment;
import fr.free.nrw.commons.contributions.ContributionsListFragment;
import fr.free.nrw.commons.customselector.ui.selector.FolderFragment;
import fr.free.nrw.commons.customselector.ui.selector.ImageFragment;
import fr.free.nrw.commons.explore.ExploreFragment;
import fr.free.nrw.commons.explore.ExploreListRootFragment;
import fr.free.nrw.commons.explore.ExploreMapRootFragment;
import fr.free.nrw.commons.explore.map.ExploreMapFragment;
import fr.free.nrw.commons.explore.categories.media.CategoriesMediaFragment;
import fr.free.nrw.commons.explore.categories.parent.ParentCategoriesFragment;
import fr.free.nrw.commons.explore.categories.search.SearchCategoryFragment;
import fr.free.nrw.commons.explore.categories.sub.SubCategoriesFragment;
import fr.free.nrw.commons.explore.depictions.child.ChildDepictionsFragment;
import fr.free.nrw.commons.explore.depictions.media.DepictedImagesFragment;
import fr.free.nrw.commons.explore.depictions.parent.ParentDepictionsFragment;
import fr.free.nrw.commons.explore.depictions.search.SearchDepictionsFragment;
import fr.free.nrw.commons.explore.media.SearchMediaFragment;
import fr.free.nrw.commons.explore.recentsearches.RecentSearchesFragment;
import fr.free.nrw.commons.media.MediaDetailFragment;
import fr.free.nrw.commons.media.MediaDetailPagerFragment;
import fr.free.nrw.commons.navtab.MoreBottomSheetFragment;
import fr.free.nrw.commons.navtab.MoreBottomSheetLoggedOutFragment;
import fr.free.nrw.commons.nearby.fragments.NearbyParentFragment;
import fr.free.nrw.commons.profile.achievements.AchievementsFragment;
import fr.free.nrw.commons.profile.leaderboard.LeaderboardFragment;
import fr.free.nrw.commons.review.ReviewImageFragment;
import fr.free.nrw.commons.settings.SettingsFragment;
import fr.free.nrw.commons.upload.FailedUploadsFragment;
import fr.free.nrw.commons.upload.PendingUploadsFragment;
import fr.free.nrw.commons.upload.categories.UploadCategoriesFragment;
import fr.free.nrw.commons.upload.depicts.DepictsFragment;
import fr.free.nrw.commons.upload.license.MediaLicenseFragment;
import fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailFragment;
/**
* This Class Represents the Module for dependency injection (using dagger)
* so, if a developer needs to add a new Fragment to the commons app
* then that must be mentioned here to inject the dependencies
*/
@Module
@SuppressWarnings({"WeakerAccess", "unused"})
public abstract class FragmentBuilderModule {
@ContributesAndroidInjector
abstract ContributionsListFragment bindContributionsListFragment();
@ContributesAndroidInjector
abstract MediaDetailFragment bindMediaDetailFragment();
@ContributesAndroidInjector
abstract FolderFragment bindFolderFragment();
@ContributesAndroidInjector
abstract ImageFragment bindImageFragment();
@ContributesAndroidInjector
abstract MediaDetailPagerFragment bindMediaDetailPagerFragment();
@ContributesAndroidInjector
abstract SettingsFragment bindSettingsFragment();
@ContributesAndroidInjector
abstract DepictedImagesFragment bindDepictedImagesFragment();
@ContributesAndroidInjector
abstract SearchMediaFragment bindBrowseImagesListFragment();
@ContributesAndroidInjector
abstract SearchCategoryFragment bindSearchCategoryListFragment();
@ContributesAndroidInjector
abstract SearchDepictionsFragment bindSearchDepictionListFragment();
@ContributesAndroidInjector
abstract RecentSearchesFragment bindRecentSearchesFragment();
@ContributesAndroidInjector
abstract ContributionsFragment bindContributionsFragment();
@ContributesAndroidInjector(modules = NearbyParentFragmentModule.class)
abstract NearbyParentFragment bindNearbyParentFragment();
@ContributesAndroidInjector
abstract BookmarkPicturesFragment bindBookmarkPictureListFragment();
@ContributesAndroidInjector(modules = BookmarkLocationsFragmentModule.class)
abstract BookmarkLocationsFragment bindBookmarkLocationListFragment();
@ContributesAndroidInjector(modules = BookmarkItemsFragmentModule.class)
abstract BookmarkItemsFragment bindBookmarkItemListFragment();
@ContributesAndroidInjector
abstract ReviewImageFragment bindReviewOutOfContextFragment();
@ContributesAndroidInjector
abstract UploadMediaDetailFragment bindUploadMediaDetailFragment();
@ContributesAndroidInjector
abstract UploadCategoriesFragment bindUploadCategoriesFragment();
@ContributesAndroidInjector
abstract DepictsFragment bindDepictsFragment();
@ContributesAndroidInjector
abstract MediaLicenseFragment bindMediaLicenseFragment();
@ContributesAndroidInjector
abstract ParentDepictionsFragment bindParentDepictionsFragment();
@ContributesAndroidInjector
abstract ChildDepictionsFragment bindChildDepictionsFragment();
@ContributesAndroidInjector
abstract CategoriesMediaFragment bindCategoriesMediaFragment();
@ContributesAndroidInjector
abstract SubCategoriesFragment bindSubCategoriesFragment();
@ContributesAndroidInjector
abstract ParentCategoriesFragment bindParentCategoriesFragment();
@ContributesAndroidInjector
abstract ExploreFragment bindExploreFragmentFragment();
@ContributesAndroidInjector
abstract ExploreListRootFragment bindExploreFeaturedRootFragment();
@ContributesAndroidInjector(modules = ExploreMapFragmentModule.class)
abstract ExploreMapFragment bindExploreNearbyUploadsFragment();
@ContributesAndroidInjector
abstract ExploreMapRootFragment bindExploreNearbyUploadsRootFragment();
@ContributesAndroidInjector
abstract BookmarkListRootFragment bindBookmarkListRootFragment();
@ContributesAndroidInjector
abstract BookmarkFragment bindBookmarkFragmentFragment();
@ContributesAndroidInjector
abstract MoreBottomSheetFragment bindMoreBottomSheetFragment();
@ContributesAndroidInjector
abstract MoreBottomSheetLoggedOutFragment bindMoreBottomSheetLoggedOutFragment();
@ContributesAndroidInjector
abstract AchievementsFragment bindAchievementsFragment();
@ContributesAndroidInjector
abstract LeaderboardFragment bindLeaderboardFragment();
@ContributesAndroidInjector
abstract PendingUploadsFragment bindPendingUploadsFragment();
@ContributesAndroidInjector
abstract FailedUploadsFragment bindFailedUploadsFragment();
}

View file

@ -0,0 +1,165 @@
package fr.free.nrw.commons.di
import dagger.Module
import dagger.android.ContributesAndroidInjector
import fr.free.nrw.commons.bookmarks.BookmarkFragment
import fr.free.nrw.commons.bookmarks.BookmarkListRootFragment
import fr.free.nrw.commons.bookmarks.items.BookmarkItemsFragment
import fr.free.nrw.commons.bookmarks.locations.BookmarkLocationsFragment
import fr.free.nrw.commons.bookmarks.pictures.BookmarkPicturesFragment
import fr.free.nrw.commons.contributions.ContributionsFragment
import fr.free.nrw.commons.contributions.ContributionsListFragment
import fr.free.nrw.commons.customselector.ui.selector.FolderFragment
import fr.free.nrw.commons.customselector.ui.selector.ImageFragment
import fr.free.nrw.commons.explore.ExploreFragment
import fr.free.nrw.commons.explore.ExploreListRootFragment
import fr.free.nrw.commons.explore.ExploreMapRootFragment
import fr.free.nrw.commons.explore.categories.media.CategoriesMediaFragment
import fr.free.nrw.commons.explore.categories.parent.ParentCategoriesFragment
import fr.free.nrw.commons.explore.categories.search.SearchCategoryFragment
import fr.free.nrw.commons.explore.categories.sub.SubCategoriesFragment
import fr.free.nrw.commons.explore.depictions.child.ChildDepictionsFragment
import fr.free.nrw.commons.explore.depictions.media.DepictedImagesFragment
import fr.free.nrw.commons.explore.depictions.parent.ParentDepictionsFragment
import fr.free.nrw.commons.explore.depictions.search.SearchDepictionsFragment
import fr.free.nrw.commons.explore.map.ExploreMapFragment
import fr.free.nrw.commons.explore.media.SearchMediaFragment
import fr.free.nrw.commons.explore.recentsearches.RecentSearchesFragment
import fr.free.nrw.commons.media.MediaDetailFragment
import fr.free.nrw.commons.media.MediaDetailPagerFragment
import fr.free.nrw.commons.navtab.MoreBottomSheetFragment
import fr.free.nrw.commons.navtab.MoreBottomSheetLoggedOutFragment
import fr.free.nrw.commons.nearby.fragments.NearbyParentFragment
import fr.free.nrw.commons.profile.achievements.AchievementsFragment
import fr.free.nrw.commons.profile.leaderboard.LeaderboardFragment
import fr.free.nrw.commons.review.ReviewImageFragment
import fr.free.nrw.commons.settings.SettingsFragment
import fr.free.nrw.commons.upload.FailedUploadsFragment
import fr.free.nrw.commons.upload.PendingUploadsFragment
import fr.free.nrw.commons.upload.categories.UploadCategoriesFragment
import fr.free.nrw.commons.upload.depicts.DepictsFragment
import fr.free.nrw.commons.upload.license.MediaLicenseFragment
import fr.free.nrw.commons.upload.mediaDetails.UploadMediaDetailFragment
/**
* This Class Represents the Module for dependency injection (using dagger)
* so, if a developer needs to add a new Fragment to the commons app
* then that must be mentioned here to inject the dependencies
*/
@Module
@Suppress("unused")
abstract class FragmentBuilderModule {
@ContributesAndroidInjector
abstract fun bindContributionsListFragment(): ContributionsListFragment
@ContributesAndroidInjector
abstract fun bindMediaDetailFragment(): MediaDetailFragment
@ContributesAndroidInjector
abstract fun bindFolderFragment(): FolderFragment
@ContributesAndroidInjector
abstract fun bindImageFragment(): ImageFragment
@ContributesAndroidInjector
abstract fun bindMediaDetailPagerFragment(): MediaDetailPagerFragment
@ContributesAndroidInjector
abstract fun bindSettingsFragment(): SettingsFragment
@ContributesAndroidInjector
abstract fun bindDepictedImagesFragment(): DepictedImagesFragment
@ContributesAndroidInjector
abstract fun bindBrowseImagesListFragment(): SearchMediaFragment
@ContributesAndroidInjector
abstract fun bindSearchCategoryListFragment(): SearchCategoryFragment
@ContributesAndroidInjector
abstract fun bindSearchDepictionListFragment(): SearchDepictionsFragment
@ContributesAndroidInjector
abstract fun bindRecentSearchesFragment(): RecentSearchesFragment
@ContributesAndroidInjector
abstract fun bindContributionsFragment(): ContributionsFragment
@ContributesAndroidInjector(modules = [NearbyParentFragmentModule::class])
abstract fun bindNearbyParentFragment(): NearbyParentFragment
@ContributesAndroidInjector
abstract fun bindBookmarkPictureListFragment(): BookmarkPicturesFragment
@ContributesAndroidInjector(modules = [BookmarkLocationsFragmentModule::class])
abstract fun bindBookmarkLocationListFragment(): BookmarkLocationsFragment
@ContributesAndroidInjector(modules = [BookmarkItemsFragmentModule::class])
abstract fun bindBookmarkItemListFragment(): BookmarkItemsFragment
@ContributesAndroidInjector
abstract fun bindReviewOutOfContextFragment(): ReviewImageFragment
@ContributesAndroidInjector
abstract fun bindUploadMediaDetailFragment(): UploadMediaDetailFragment
@ContributesAndroidInjector
abstract fun bindUploadCategoriesFragment(): UploadCategoriesFragment
@ContributesAndroidInjector
abstract fun bindDepictsFragment(): DepictsFragment
@ContributesAndroidInjector
abstract fun bindMediaLicenseFragment(): MediaLicenseFragment
@ContributesAndroidInjector
abstract fun bindParentDepictionsFragment(): ParentDepictionsFragment
@ContributesAndroidInjector
abstract fun bindChildDepictionsFragment(): ChildDepictionsFragment
@ContributesAndroidInjector
abstract fun bindCategoriesMediaFragment(): CategoriesMediaFragment
@ContributesAndroidInjector
abstract fun bindSubCategoriesFragment(): SubCategoriesFragment
@ContributesAndroidInjector
abstract fun bindParentCategoriesFragment(): ParentCategoriesFragment
@ContributesAndroidInjector
abstract fun bindExploreFragmentFragment(): ExploreFragment
@ContributesAndroidInjector
abstract fun bindExploreFeaturedRootFragment(): ExploreListRootFragment
@ContributesAndroidInjector(modules = [ExploreMapFragmentModule::class])
abstract fun bindExploreNearbyUploadsFragment(): ExploreMapFragment
@ContributesAndroidInjector
abstract fun bindExploreNearbyUploadsRootFragment(): ExploreMapRootFragment
@ContributesAndroidInjector
abstract fun bindBookmarkListRootFragment(): BookmarkListRootFragment
@ContributesAndroidInjector
abstract fun bindBookmarkFragmentFragment(): BookmarkFragment
@ContributesAndroidInjector
abstract fun bindMoreBottomSheetFragment(): MoreBottomSheetFragment
@ContributesAndroidInjector
abstract fun bindMoreBottomSheetLoggedOutFragment(): MoreBottomSheetLoggedOutFragment
@ContributesAndroidInjector
abstract fun bindAchievementsFragment(): AchievementsFragment
@ContributesAndroidInjector
abstract fun bindLeaderboardFragment(): LeaderboardFragment
@ContributesAndroidInjector
abstract fun bindPendingUploadsFragment(): PendingUploadsFragment
@ContributesAndroidInjector
abstract fun bindFailedUploadsFragment(): FailedUploadsFragment
}

View file

@ -1,350 +0,0 @@
package fr.free.nrw.commons.di;
import android.content.Context;
import androidx.annotation.NonNull;
import com.google.gson.Gson;
import dagger.Module;
import dagger.Provides;
import fr.free.nrw.commons.BetaConstants;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.OkHttpConnectionFactory;
import fr.free.nrw.commons.actions.PageEditClient;
import fr.free.nrw.commons.actions.PageEditInterface;
import fr.free.nrw.commons.actions.ThanksInterface;
import fr.free.nrw.commons.auth.SessionManager;
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient;
import fr.free.nrw.commons.auth.csrf.CsrfTokenInterface;
import fr.free.nrw.commons.auth.csrf.LogoutClient;
import fr.free.nrw.commons.auth.login.LoginClient;
import fr.free.nrw.commons.auth.login.LoginInterface;
import fr.free.nrw.commons.category.CategoryInterface;
import fr.free.nrw.commons.explore.depictions.DepictsClient;
import fr.free.nrw.commons.kvstore.JsonKvStore;
import fr.free.nrw.commons.media.MediaDetailInterface;
import fr.free.nrw.commons.media.MediaInterface;
import fr.free.nrw.commons.media.PageMediaInterface;
import fr.free.nrw.commons.media.WikidataMediaInterface;
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient;
import fr.free.nrw.commons.mwapi.UserInterface;
import fr.free.nrw.commons.notification.NotificationInterface;
import fr.free.nrw.commons.review.ReviewInterface;
import fr.free.nrw.commons.upload.UploadInterface;
import fr.free.nrw.commons.upload.WikiBaseInterface;
import fr.free.nrw.commons.upload.depicts.DepictsInterface;
import fr.free.nrw.commons.wikidata.CommonsServiceFactory;
import fr.free.nrw.commons.wikidata.WikidataInterface;
import fr.free.nrw.commons.wikidata.cookies.CommonsCookieJar;
import fr.free.nrw.commons.wikidata.cookies.CommonsCookieStorage;
import java.io.File;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
import okhttp3.Cache;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import okhttp3.logging.HttpLoggingInterceptor.Level;
import fr.free.nrw.commons.wikidata.model.WikiSite;
import fr.free.nrw.commons.wikidata.GsonUtil;
import timber.log.Timber;
@Module
@SuppressWarnings({"WeakerAccess", "unused"})
public class NetworkingModule {
private static final String WIKIDATA_SPARQL_QUERY_URL = "https://query.wikidata.org/sparql";
private static final String TOOLS_FORGE_URL = "https://tools.wmflabs.org/commons-android-app/tool-commons-android-app";
public static final long OK_HTTP_CACHE_SIZE = 10 * 1024 * 1024;
private static final String NAMED_WIKI_DATA_WIKI_SITE = "wikidata-wikisite";
private static final String NAMED_WIKI_PEDIA_WIKI_SITE = "wikipedia-wikisite";
public static final String NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE = "language-wikipedia-wikisite";
public static final String NAMED_COMMONS_CSRF = "commons-csrf";
public static final String NAMED_WIKI_CSRF = "wiki-csrf";
@Provides
@Singleton
public OkHttpClient provideOkHttpClient(Context context,
HttpLoggingInterceptor httpLoggingInterceptor) {
File dir = new File(context.getCacheDir(), "okHttpCache");
return new OkHttpClient.Builder()
.connectTimeout(120, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.addInterceptor(httpLoggingInterceptor)
.readTimeout(120, TimeUnit.SECONDS)
.cache(new Cache(dir, OK_HTTP_CACHE_SIZE))
.build();
}
@Provides
@Singleton
public CommonsServiceFactory serviceFactory(CommonsCookieJar cookieJar) {
return new CommonsServiceFactory(OkHttpConnectionFactory.getClient(cookieJar));
}
@Provides
@Singleton
public HttpLoggingInterceptor provideHttpLoggingInterceptor() {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(message -> {
Timber.tag("OkHttp").v(message);
});
httpLoggingInterceptor.setLevel(BuildConfig.DEBUG ? Level.BODY: Level.BASIC);
return httpLoggingInterceptor;
}
@Provides
@Singleton
public OkHttpJsonApiClient provideOkHttpJsonApiClient(OkHttpClient okHttpClient,
DepictsClient depictsClient,
@Named("tools_forge") HttpUrl toolsForgeUrl,
@Named("default_preferences") JsonKvStore defaultKvStore,
Gson gson) {
return new OkHttpJsonApiClient(okHttpClient,
depictsClient,
toolsForgeUrl,
WIKIDATA_SPARQL_QUERY_URL,
BuildConfig.WIKIMEDIA_CAMPAIGNS_URL,
gson);
}
@Provides
@Singleton
public CommonsCookieStorage provideCookieStorage(
@Named("default_preferences") JsonKvStore preferences) {
CommonsCookieStorage cookieStorage = new CommonsCookieStorage(preferences);
cookieStorage.load();
return cookieStorage;
}
@Provides
@Singleton
public CommonsCookieJar provideCookieJar(CommonsCookieStorage storage) {
return new CommonsCookieJar(storage);
}
@Named(NAMED_COMMONS_CSRF)
@Provides
@Singleton
public CsrfTokenClient provideCommonsCsrfTokenClient(SessionManager sessionManager,
@Named("commons-csrf-interface") CsrfTokenInterface tokenInterface, LoginClient loginClient, LogoutClient logoutClient) {
return new CsrfTokenClient(sessionManager, tokenInterface, loginClient, logoutClient);
}
/**
* Provides a singleton instance of CsrfTokenClient for Wikidata.
*
* @param sessionManager The session manager to manage user sessions.
* @param tokenInterface The interface for obtaining CSRF tokens.
* @param loginClient The client for handling login operations.
* @param logoutClient The client for handling logout operations.
* @return A singleton instance of CsrfTokenClient.
*/
@Named(NAMED_WIKI_CSRF)
@Provides
@Singleton
public CsrfTokenClient provideWikiCsrfTokenClient(SessionManager sessionManager,
@Named("wikidata-csrf-interface") CsrfTokenInterface tokenInterface, LoginClient loginClient, LogoutClient logoutClient) {
return new CsrfTokenClient(sessionManager, tokenInterface, loginClient, logoutClient);
}
/**
* Provides a singleton instance of CsrfTokenInterface for Wikidata.
*
* @param serviceFactory The factory used to create service interfaces.
* @return A singleton instance of CsrfTokenInterface for Wikidata.
*/
@Named("wikidata-csrf-interface")
@Provides
@Singleton
public CsrfTokenInterface provideWikidataCsrfTokenInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.WIKIDATA_URL, CsrfTokenInterface.class);
}
@Named("commons-csrf-interface")
@Provides
@Singleton
public CsrfTokenInterface provideCsrfTokenInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.COMMONS_URL, CsrfTokenInterface.class);
}
@Provides
@Singleton
public LoginInterface provideLoginInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.COMMONS_URL, LoginInterface.class);
}
@Provides
@Singleton
public LoginClient provideLoginClient(LoginInterface loginInterface) {
return new LoginClient(loginInterface);
}
@Provides
@Named("wikimedia_api_host")
@NonNull
@SuppressWarnings("ConstantConditions")
public String provideMwApiUrl() {
return BuildConfig.WIKIMEDIA_API_HOST;
}
@Provides
@Named("tools_forge")
@NonNull
@SuppressWarnings("ConstantConditions")
public HttpUrl provideToolsForgeUrl() {
return HttpUrl.parse(TOOLS_FORGE_URL);
}
@Provides
@Singleton
@Named(NAMED_WIKI_DATA_WIKI_SITE)
public WikiSite provideWikidataWikiSite() {
return new WikiSite(BuildConfig.WIKIDATA_URL);
}
/**
* Gson objects are very heavy. The app should ideally be using just one instance of it instead of creating new instances everywhere.
* @return returns a singleton Gson instance
*/
@Provides
@Singleton
public Gson provideGson() {
return GsonUtil.getDefaultGson();
}
@Provides
@Singleton
public ReviewInterface provideReviewInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.COMMONS_URL, ReviewInterface.class);
}
@Provides
@Singleton
public DepictsInterface provideDepictsInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.WIKIDATA_URL, DepictsInterface.class);
}
@Provides
@Singleton
public WikiBaseInterface provideWikiBaseInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.COMMONS_URL, WikiBaseInterface.class);
}
@Provides
@Singleton
public UploadInterface provideUploadInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.COMMONS_URL, UploadInterface.class);
}
@Named("commons-page-edit-service")
@Provides
@Singleton
public PageEditInterface providePageEditService(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.COMMONS_URL, PageEditInterface.class);
}
@Named("wikidata-page-edit-service")
@Provides
@Singleton
public PageEditInterface provideWikiDataPageEditService(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.WIKIDATA_URL, PageEditInterface.class);
}
@Named("commons-page-edit")
@Provides
@Singleton
public PageEditClient provideCommonsPageEditClient(@Named(NAMED_COMMONS_CSRF) CsrfTokenClient csrfTokenClient,
@Named("commons-page-edit-service") PageEditInterface pageEditInterface) {
return new PageEditClient(csrfTokenClient, pageEditInterface);
}
/**
* Provides a singleton instance of PageEditClient for Wikidata.
*
* @param csrfTokenClient The client used to manage CSRF tokens.
* @param pageEditInterface The interface for page edit operations.
* @return A singleton instance of PageEditClient for Wikidata.
*/
@Named("wikidata-page-edit")
@Provides
@Singleton
public PageEditClient provideWikidataPageEditClient(@Named(NAMED_WIKI_CSRF) CsrfTokenClient csrfTokenClient,
@Named("wikidata-page-edit-service") PageEditInterface pageEditInterface) {
return new PageEditClient(csrfTokenClient, pageEditInterface);
}
@Provides
@Singleton
public MediaInterface provideMediaInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.COMMONS_URL, MediaInterface.class);
}
/**
* Add provider for WikidataMediaInterface
* It creates a retrofit service for the commons wiki site
* @param commonsWikiSite commonsWikiSite
* @return WikidataMediaInterface
*/
@Provides
@Singleton
public WikidataMediaInterface provideWikidataMediaInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BetaConstants.COMMONS_URL, WikidataMediaInterface.class);
}
@Provides
@Singleton
public MediaDetailInterface providesMediaDetailInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.COMMONS_URL, MediaDetailInterface.class);
}
@Provides
@Singleton
public CategoryInterface provideCategoryInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.COMMONS_URL, CategoryInterface.class);
}
@Provides
@Singleton
public ThanksInterface provideThanksInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.COMMONS_URL, ThanksInterface.class);
}
@Provides
@Singleton
public NotificationInterface provideNotificationInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.COMMONS_URL, NotificationInterface.class);
}
@Provides
@Singleton
public UserInterface provideUserInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.COMMONS_URL, UserInterface.class);
}
@Provides
@Singleton
public WikidataInterface provideWikidataInterface(CommonsServiceFactory serviceFactory) {
return serviceFactory.create(BuildConfig.WIKIDATA_URL, WikidataInterface.class);
}
/**
* Add provider for PageMediaInterface
* It creates a retrofit service for the wiki site using device's current language
*/
@Provides
@Singleton
public PageMediaInterface providePageMediaInterface(@Named(NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE) WikiSite wikiSite, CommonsServiceFactory serviceFactory) {
return serviceFactory.create(wikiSite.url(), PageMediaInterface.class);
}
@Provides
@Singleton
@Named(NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE)
public WikiSite provideLanguageWikipediaSite() {
return WikiSite.forLanguageCode(Locale.getDefault().getLanguage());
}
}

View file

@ -0,0 +1,316 @@
package fr.free.nrw.commons.di
import android.content.Context
import com.google.gson.Gson
import dagger.Module
import dagger.Provides
import fr.free.nrw.commons.BetaConstants
import fr.free.nrw.commons.BuildConfig
import fr.free.nrw.commons.OkHttpConnectionFactory
import fr.free.nrw.commons.actions.PageEditClient
import fr.free.nrw.commons.actions.PageEditInterface
import fr.free.nrw.commons.actions.ThanksInterface
import fr.free.nrw.commons.auth.SessionManager
import fr.free.nrw.commons.auth.csrf.CsrfTokenClient
import fr.free.nrw.commons.auth.csrf.CsrfTokenInterface
import fr.free.nrw.commons.auth.csrf.LogoutClient
import fr.free.nrw.commons.auth.login.LoginClient
import fr.free.nrw.commons.auth.login.LoginInterface
import fr.free.nrw.commons.category.CategoryInterface
import fr.free.nrw.commons.explore.depictions.DepictsClient
import fr.free.nrw.commons.kvstore.JsonKvStore
import fr.free.nrw.commons.media.MediaDetailInterface
import fr.free.nrw.commons.media.MediaInterface
import fr.free.nrw.commons.media.PageMediaInterface
import fr.free.nrw.commons.media.WikidataMediaInterface
import fr.free.nrw.commons.mwapi.OkHttpJsonApiClient
import fr.free.nrw.commons.mwapi.UserInterface
import fr.free.nrw.commons.notification.NotificationInterface
import fr.free.nrw.commons.review.ReviewInterface
import fr.free.nrw.commons.upload.UploadInterface
import fr.free.nrw.commons.upload.WikiBaseInterface
import fr.free.nrw.commons.upload.depicts.DepictsInterface
import fr.free.nrw.commons.wikidata.CommonsServiceFactory
import fr.free.nrw.commons.wikidata.GsonUtil
import fr.free.nrw.commons.wikidata.WikidataInterface
import fr.free.nrw.commons.wikidata.cookies.CommonsCookieJar
import fr.free.nrw.commons.wikidata.cookies.CommonsCookieStorage
import fr.free.nrw.commons.wikidata.model.WikiSite
import okhttp3.Cache
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import okhttp3.logging.HttpLoggingInterceptor.Level
import timber.log.Timber
import java.io.File
import java.util.Locale
import java.util.concurrent.TimeUnit
import javax.inject.Named
import javax.inject.Singleton
@Module
@Suppress("unused")
class NetworkingModule {
@Provides
@Singleton
fun provideOkHttpClient(
context: Context,
httpLoggingInterceptor: HttpLoggingInterceptor
): OkHttpClient = OkHttpClient.Builder()
.connectTimeout(120, TimeUnit.SECONDS)
.writeTimeout(120, TimeUnit.SECONDS)
.addInterceptor(httpLoggingInterceptor)
.readTimeout(120, TimeUnit.SECONDS)
.cache(Cache(File(context.cacheDir, "okHttpCache"), OK_HTTP_CACHE_SIZE))
.build()
@Provides
@Singleton
fun serviceFactory(cookieJar: CommonsCookieJar): CommonsServiceFactory =
CommonsServiceFactory(OkHttpConnectionFactory.getClient(cookieJar))
@Provides
@Singleton
fun provideHttpLoggingInterceptor(): HttpLoggingInterceptor =
HttpLoggingInterceptor { message: String? ->
Timber.tag("OkHttp").v(message)
}.apply {
level = if (BuildConfig.DEBUG) Level.BODY else Level.BASIC
}
@Provides
@Singleton
fun provideOkHttpJsonApiClient(
okHttpClient: OkHttpClient,
depictsClient: DepictsClient,
@Named("tools_forge") toolsForgeUrl: HttpUrl,
gson: Gson
): OkHttpJsonApiClient = OkHttpJsonApiClient(
okHttpClient, depictsClient, toolsForgeUrl, WIKIDATA_SPARQL_QUERY_URL,
BuildConfig.WIKIMEDIA_CAMPAIGNS_URL, gson
)
@Provides
@Singleton
fun provideCookieStorage(
@Named("default_preferences") preferences: JsonKvStore
): CommonsCookieStorage = CommonsCookieStorage(preferences).also {
it.load()
}
@Provides
@Singleton
fun provideCookieJar(storage: CommonsCookieStorage): CommonsCookieJar =
CommonsCookieJar(storage)
@Named(NAMED_COMMONS_CSRF)
@Provides
@Singleton
fun provideCommonsCsrfTokenClient(
sessionManager: SessionManager,
@Named("commons-csrf-interface") tokenInterface: CsrfTokenInterface,
loginClient: LoginClient,
logoutClient: LogoutClient
): CsrfTokenClient = CsrfTokenClient(sessionManager, tokenInterface, loginClient, logoutClient)
/**
* Provides a singleton instance of CsrfTokenClient for Wikidata.
*
* @param sessionManager The session manager to manage user sessions.
* @param tokenInterface The interface for obtaining CSRF tokens.
* @param loginClient The client for handling login operations.
* @param logoutClient The client for handling logout operations.
* @return A singleton instance of CsrfTokenClient.
*/
@Named(NAMED_WIKI_CSRF)
@Provides
@Singleton
fun provideWikiCsrfTokenClient(
sessionManager: SessionManager,
@Named("wikidata-csrf-interface") tokenInterface: CsrfTokenInterface,
loginClient: LoginClient,
logoutClient: LogoutClient
): CsrfTokenClient = CsrfTokenClient(sessionManager, tokenInterface, loginClient, logoutClient)
/**
* Provides a singleton instance of CsrfTokenInterface for Wikidata.
*
* @param factory The factory used to create service interfaces.
* @return A singleton instance of CsrfTokenInterface for Wikidata.
*/
@Named("wikidata-csrf-interface")
@Provides
@Singleton
fun provideWikidataCsrfTokenInterface(factory: CommonsServiceFactory): CsrfTokenInterface =
factory.create(BuildConfig.WIKIDATA_URL)
@Named("commons-csrf-interface")
@Provides
@Singleton
fun provideCsrfTokenInterface(factory: CommonsServiceFactory): CsrfTokenInterface =
factory.create(BuildConfig.COMMONS_URL)
@Provides
@Singleton
fun provideLoginInterface(factory: CommonsServiceFactory): LoginInterface =
factory.create(BuildConfig.COMMONS_URL)
@Provides
@Singleton
fun provideLoginClient(loginInterface: LoginInterface): LoginClient =
LoginClient(loginInterface)
@Provides
@Named("tools_forge")
fun provideToolsForgeUrl(): HttpUrl = TOOLS_FORGE_URL.toHttpUrlOrNull()!!
@Provides
@Singleton
@Named(NAMED_WIKI_DATA_WIKI_SITE)
fun provideWikidataWikiSite(): WikiSite = WikiSite(BuildConfig.WIKIDATA_URL)
/**
* Gson objects are very heavy. The app should ideally be using just one instance of it instead of creating new instances everywhere.
* @return returns a singleton Gson instance
*/
@Provides
@Singleton
fun provideGson(): Gson = GsonUtil.getDefaultGson()
@Provides
@Singleton
fun provideReviewInterface(factory: CommonsServiceFactory): ReviewInterface =
factory.create(BuildConfig.COMMONS_URL)
@Provides
@Singleton
fun provideDepictsInterface(factory: CommonsServiceFactory): DepictsInterface =
factory.create(BuildConfig.WIKIDATA_URL)
@Provides
@Singleton
fun provideWikiBaseInterface(factory: CommonsServiceFactory): WikiBaseInterface =
factory.create(BuildConfig.COMMONS_URL)
@Provides
@Singleton
fun provideUploadInterface(factory: CommonsServiceFactory): UploadInterface =
factory.create(BuildConfig.COMMONS_URL)
@Named("commons-page-edit-service")
@Provides
@Singleton
fun providePageEditService(factory: CommonsServiceFactory): PageEditInterface =
factory.create(BuildConfig.COMMONS_URL)
@Named("wikidata-page-edit-service")
@Provides
@Singleton
fun provideWikiDataPageEditService(factory: CommonsServiceFactory): PageEditInterface =
factory.create(BuildConfig.WIKIDATA_URL)
@Named("commons-page-edit")
@Provides
@Singleton
fun provideCommonsPageEditClient(
@Named(NAMED_COMMONS_CSRF) csrfTokenClient: CsrfTokenClient,
@Named("commons-page-edit-service") pageEditInterface: PageEditInterface
): PageEditClient = PageEditClient(csrfTokenClient, pageEditInterface)
/**
* Provides a singleton instance of PageEditClient for Wikidata.
*
* @param csrfTokenClient The client used to manage CSRF tokens.
* @param pageEditInterface The interface for page edit operations.
* @return A singleton instance of PageEditClient for Wikidata.
*/
@Named("wikidata-page-edit")
@Provides
@Singleton
fun provideWikidataPageEditClient(
@Named(NAMED_WIKI_CSRF) csrfTokenClient: CsrfTokenClient,
@Named("wikidata-page-edit-service") pageEditInterface: PageEditInterface
): PageEditClient = PageEditClient(csrfTokenClient, pageEditInterface)
@Provides
@Singleton
fun provideMediaInterface(factory: CommonsServiceFactory): MediaInterface =
factory.create(BuildConfig.COMMONS_URL)
/**
* Add provider for WikidataMediaInterface
* It creates a retrofit service for the commons wiki site
* @param commonsWikiSite commonsWikiSite
* @return WikidataMediaInterface
*/
@Provides
@Singleton
fun provideWikidataMediaInterface(factory: CommonsServiceFactory): WikidataMediaInterface =
factory.create(BetaConstants.COMMONS_URL)
@Provides
@Singleton
fun providesMediaDetailInterface(factory: CommonsServiceFactory): MediaDetailInterface =
factory.create(BuildConfig.COMMONS_URL)
@Provides
@Singleton
fun provideCategoryInterface(factory: CommonsServiceFactory): CategoryInterface =
factory.create(BuildConfig.COMMONS_URL)
@Provides
@Singleton
fun provideThanksInterface(factory: CommonsServiceFactory): ThanksInterface =
factory.create(BuildConfig.COMMONS_URL)
@Provides
@Singleton
fun provideNotificationInterface(factory: CommonsServiceFactory): NotificationInterface =
factory.create(BuildConfig.COMMONS_URL)
@Provides
@Singleton
fun provideUserInterface(factory: CommonsServiceFactory): UserInterface =
factory.create(BuildConfig.COMMONS_URL)
@Provides
@Singleton
fun provideWikidataInterface(factory: CommonsServiceFactory): WikidataInterface =
factory.create(BuildConfig.WIKIDATA_URL)
/**
* Add provider for PageMediaInterface
* It creates a retrofit service for the wiki site using device's current language
*/
@Provides
@Singleton
fun providePageMediaInterface(
@Named(NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE) wikiSite: WikiSite,
factory: CommonsServiceFactory
): PageMediaInterface = factory.create(wikiSite.url())
@Provides
@Singleton
@Named(NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE)
fun provideLanguageWikipediaSite(): WikiSite {
return WikiSite.forLanguageCode(Locale.getDefault().language)
}
companion object {
private const val WIKIDATA_SPARQL_QUERY_URL = "https://query.wikidata.org/sparql"
private const val TOOLS_FORGE_URL =
"https://tools.wmflabs.org/commons-android-app/tool-commons-android-app"
const val OK_HTTP_CACHE_SIZE: Long = (10 * 1024 * 1024).toLong()
private const val NAMED_WIKI_DATA_WIKI_SITE = "wikidata-wikisite"
private const val NAMED_WIKI_PEDIA_WIKI_SITE = "wikipedia-wikisite"
const val NAMED_LANGUAGE_WIKI_PEDIA_WIKI_SITE: String = "language-wikipedia-wikisite"
const val NAMED_COMMONS_CSRF: String = "commons-csrf"
const val NAMED_WIKI_CSRF: String = "wiki-csrf"
}
}

View file

@ -1,19 +0,0 @@
package fr.free.nrw.commons.di;
import dagger.Module;
import dagger.android.ContributesAndroidInjector;
import fr.free.nrw.commons.auth.WikiAccountAuthenticatorService;
/**
* This Class Represents the Module for dependency injection (using dagger)
* so, if a developer needs to add a new Service to the commons app
* then that must be mentioned here to inject the dependencies
*/
@Module
@SuppressWarnings({"WeakerAccess", "unused"})
public abstract class ServiceBuilderModule {
@ContributesAndroidInjector
abstract WikiAccountAuthenticatorService bindWikiAccountAuthenticatorService();
}

View file

@ -0,0 +1,17 @@
package fr.free.nrw.commons.di
import dagger.Module
import dagger.android.ContributesAndroidInjector
import fr.free.nrw.commons.auth.WikiAccountAuthenticatorService
/**
* This Class Represents the Module for dependency injection (using dagger)
* so, if a developer needs to add a new Service to the commons app
* then that must be mentioned here to inject the dependencies
*/
@Module
@Suppress("unused")
abstract class ServiceBuilderModule {
@ContributesAndroidInjector
abstract fun bindWikiAccountAuthenticatorService(): WikiAccountAuthenticatorService
}

View file

@ -3,7 +3,10 @@ package fr.free.nrw.commons.mwapi;
import static fr.free.nrw.commons.category.CategoryClientKt.CATEGORY_PREFIX;
import com.google.gson.Gson;
import fr.free.nrw.commons.BuildConfig;
import fr.free.nrw.commons.category.CategoryItem;
import fr.free.nrw.commons.wikidata.mwapi.MwQueryPage;
import fr.free.nrw.commons.wikidata.mwapi.MwQueryResponse;
import io.reactivex.Single;
import java.util.ArrayList;
import java.util.Collections;
@ -11,14 +14,11 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Named;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import fr.free.nrw.commons.wikidata.mwapi.MwQueryPage;
import fr.free.nrw.commons.wikidata.mwapi.MwQueryResponse;
import timber.log.Timber;
/**
@ -30,14 +30,11 @@ import timber.log.Timber;
public class CategoryApi {
private final OkHttpClient okHttpClient;
private final String commonsBaseUrl;
private final Gson gson;
@Inject
public CategoryApi(OkHttpClient okHttpClient, Gson gson,
@Named("wikimedia_api_host") String commonsBaseUrl) {
public CategoryApi(final OkHttpClient okHttpClient, final Gson gson) {
this.okHttpClient = okHttpClient;
this.commonsBaseUrl = commonsBaseUrl;
this.gson = gson;
}
@ -75,9 +72,9 @@ public class CategoryApi {
* @param coords Coordinates to build query with
* @return URL for API query
*/
private HttpUrl buildUrl(String coords) {
private HttpUrl buildUrl(final String coords) {
return HttpUrl
.parse(commonsBaseUrl)
.parse(BuildConfig.WIKIMEDIA_API_HOST)
.newBuilder()
.addQueryParameter("action", "query")
.addQueryParameter("prop", "categories|coordinates|pageprops")

View file

@ -1,6 +1,7 @@
package fr.free.nrw.commons.upload;
import static fr.free.nrw.commons.di.CommonsApplicationModule.IO_THREAD;
import static fr.free.nrw.commons.utils.ImageUtils.IMAGE_OK;
import android.content.Context;
@ -53,7 +54,7 @@ public class PendingUploadsPresenter implements UserActionListener {
final ContributionsRemoteDataSource contributionsRemoteDataSource,
final ContributionsRepository contributionsRepository,
final UploadRepository uploadRepository,
@Named(CommonsApplicationModule.IO_THREAD) final Scheduler ioThreadScheduler) {
@Named(IO_THREAD) final Scheduler ioThreadScheduler) {
this.contributionBoundaryCallback = contributionBoundaryCallback;
this.contributionsRepository = contributionsRepository;
this.uploadRepository = uploadRepository;

View file

@ -9,6 +9,8 @@ import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException
import fr.free.nrw.commons.category.CategoryEditHelper
import fr.free.nrw.commons.category.CategoryItem
import fr.free.nrw.commons.di.CommonsApplicationModule
import fr.free.nrw.commons.di.CommonsApplicationModule.Companion.IO_THREAD
import fr.free.nrw.commons.di.CommonsApplicationModule.Companion.MAIN_THREAD
import fr.free.nrw.commons.repository.UploadRepository
import fr.free.nrw.commons.upload.depicts.proxy
import io.reactivex.Observable
@ -30,8 +32,8 @@ class CategoriesPresenter
@Inject
constructor(
private val repository: UploadRepository,
@param:Named(CommonsApplicationModule.IO_THREAD) private val ioScheduler: Scheduler,
@param:Named(CommonsApplicationModule.MAIN_THREAD) private val mainThreadScheduler: Scheduler,
@param:Named(IO_THREAD) private val ioScheduler: Scheduler,
@param:Named(MAIN_THREAD) private val mainThreadScheduler: Scheduler,
) : CategoriesContract.UserActionListener {
companion object {
private val DUMMY: CategoriesContract.View = proxy()

View file

@ -7,6 +7,8 @@ import fr.free.nrw.commons.Media
import fr.free.nrw.commons.auth.csrf.InvalidLoginTokenException
import fr.free.nrw.commons.bookmarks.items.BookmarkItemsController
import fr.free.nrw.commons.di.CommonsApplicationModule
import fr.free.nrw.commons.di.CommonsApplicationModule.Companion.IO_THREAD
import fr.free.nrw.commons.di.CommonsApplicationModule.Companion.MAIN_THREAD
import fr.free.nrw.commons.repository.UploadRepository
import fr.free.nrw.commons.upload.structure.depictions.DepictedItem
import fr.free.nrw.commons.wikidata.WikidataDisambiguationItems
@ -31,8 +33,8 @@ class DepictsPresenter
@Inject
constructor(
private val repository: UploadRepository,
@param:Named(CommonsApplicationModule.IO_THREAD) private val ioScheduler: Scheduler,
@param:Named(CommonsApplicationModule.MAIN_THREAD) private val mainThreadScheduler: Scheduler,
@param:Named(IO_THREAD) private val ioScheduler: Scheduler,
@param:Named(MAIN_THREAD) private val mainThreadScheduler: Scheduler,
) : DepictsContract.UserActionListener {
companion object {
private val DUMMY = proxy<DepictsContract.View>()

View file

@ -8,7 +8,7 @@ import retrofit2.converter.gson.GsonConverterFactory
class CommonsServiceFactory(
private val okHttpClient: OkHttpClient,
) {
private val builder: Retrofit.Builder by lazy {
val builder: Retrofit.Builder by lazy {
// All instances of retrofit share this configuration, but create it lazily
Retrofit
.Builder()
@ -17,15 +17,11 @@ class CommonsServiceFactory(
.addConverterFactory(GsonConverterFactory.create(GsonUtil.getDefaultGson()))
}
private val retrofitCache: MutableMap<String, Retrofit> = mutableMapOf()
val retrofitCache: MutableMap<String, Retrofit> = mutableMapOf()
fun <T : Any> create(
baseUrl: String,
service: Class<T>,
): T =
retrofitCache
.getOrPut(baseUrl) {
// Cache instances of retrofit based on API backend
builder.baseUrl(baseUrl).build()
}.create(service)
inline fun <reified T: Any> create(baseUrl: String): T =
retrofitCache.getOrPut(baseUrl) {
// Cache instances of retrofit based on API backend
builder.baseUrl(baseUrl).build()
}.create(T::class.java)
}

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