diff --git a/app/src/main/java/com/duckduckgo/app/bookmarks/ui/BookmarksViewModel.kt b/app/src/main/java/com/duckduckgo/app/bookmarks/ui/BookmarksViewModel.kt index b550a3f36744..1656deae3e72 100644 --- a/app/src/main/java/com/duckduckgo/app/bookmarks/ui/BookmarksViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/bookmarks/ui/BookmarksViewModel.kt @@ -28,9 +28,16 @@ import com.duckduckgo.app.bookmarks.ui.EditBookmarkDialogFragment.EditBookmarkLi import com.duckduckgo.app.browser.favicon.FaviconManager import com.duckduckgo.app.global.DispatcherProvider import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import io.reactivex.schedulers.Schedulers import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.launch +import javax.inject.Singleton class BookmarksViewModel( val dao: BookmarksDao, @@ -112,3 +119,33 @@ class BookmarksViewModel( } } + +@Module +@ContributesTo(AppObjectGraph::class) +class BookmarksViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideBookmarksViewModelFactory( + dao: BookmarksDao, + faviconManager: FaviconManager, + dispatcherProvider: DispatcherProvider + ): ViewModelFactoryPlugin { + return BookmarksViewModelFactory(dao, faviconManager, dispatcherProvider) + } +} + +private class BookmarksViewModelFactory( + private val dao: BookmarksDao, + private val faviconManager: FaviconManager, + private val dispatcherProvider: DispatcherProvider +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(BookmarksViewModel::class.java) -> (BookmarksViewModel(dao, faviconManager, dispatcherProvider) as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/brokensite/BrokenSiteViewModel.kt b/app/src/main/java/com/duckduckgo/app/brokensite/BrokenSiteViewModel.kt index 891732a0ee44..5a93747b088c 100644 --- a/app/src/main/java/com/duckduckgo/app/brokensite/BrokenSiteViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/brokensite/BrokenSiteViewModel.kt @@ -27,7 +27,14 @@ import com.duckduckgo.app.brokensite.model.BrokenSiteCategory.* import com.duckduckgo.app.global.SingleLiveEvent import com.duckduckgo.app.global.absoluteString import com.duckduckgo.app.global.isMobileSite +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.statistics.pixels.Pixel +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet +import javax.inject.Singleton class BrokenSiteViewModel(private val pixel: Pixel, private val brokenSiteSender: BrokenSiteSender) : ViewModel() { @@ -118,3 +125,31 @@ class BrokenSiteViewModel(private val pixel: Pixel, private val brokenSiteSender const val DESKTOP_SITE = "desktop" } } + +@Module +@ContributesTo(AppObjectGraph::class) +class BrokenSiteViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideBrokenSiteViewModelFactory( + pixel: Pixel, + brokenSiteSender: BrokenSiteSender + ): ViewModelFactoryPlugin { + return BrokenSiteViewModelFactory(pixel, brokenSiteSender) + } +} + +private class BrokenSiteViewModelFactory( + private val pixel: Pixel, + private val brokenSiteSender: BrokenSiteSender +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(BrokenSiteViewModel::class.java) -> (BrokenSiteViewModel(pixel, brokenSiteSender) as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt index e30f5709f01c..3f24da3e7456 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt @@ -38,6 +38,7 @@ import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteResult import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion.AutoCompleteBookmarkSuggestion import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion.AutoCompleteSearchSuggestion +import com.duckduckgo.app.autocomplete.api.AutoCompleteApi import com.duckduckgo.app.bookmarks.db.BookmarkEntity import com.duckduckgo.app.bookmarks.db.BookmarksDao import com.duckduckgo.app.bookmarks.ui.EditBookmarkDialogFragment.EditBookmarkListener @@ -61,6 +62,7 @@ import com.duckduckgo.app.browser.model.BasicAuthenticationCredentials import com.duckduckgo.app.browser.model.BasicAuthenticationRequest import com.duckduckgo.app.browser.model.LongPressTarget import com.duckduckgo.app.browser.omnibar.OmnibarEntryConverter +import com.duckduckgo.app.browser.omnibar.QueryUrlConverter import com.duckduckgo.app.browser.session.WebViewSessionStorage import com.duckduckgo.app.browser.ui.HttpAuthenticationDialogFragment.HttpAuthenticationListener import com.duckduckgo.app.cta.ui.* @@ -73,6 +75,7 @@ import com.duckduckgo.app.global.model.Site import com.duckduckgo.app.global.model.SiteFactory import com.duckduckgo.app.global.model.domain import com.duckduckgo.app.global.model.domainMatchesUrl +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.global.useourapp.UseOurAppDetector import com.duckduckgo.app.global.useourapp.UseOurAppDetector.Companion.USE_OUR_APP_SHORTCUT_TITLE import com.duckduckgo.app.global.useourapp.UseOurAppDetector.Companion.USE_OUR_APP_SHORTCUT_URL @@ -100,7 +103,12 @@ import com.duckduckgo.app.tabs.model.TabEntity import com.duckduckgo.app.tabs.model.TabRepository import com.duckduckgo.app.trackerdetection.model.TrackingEvent import com.duckduckgo.app.usage.search.SearchCountDao +import com.duckduckgo.di.scopes.AppObjectGraph import com.jakewharton.rxrelay2.PublishRelay +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers @@ -109,6 +117,7 @@ import timber.log.Timber import java.io.File import java.util.* import java.util.concurrent.TimeUnit +import javax.inject.Singleton class BrowserTabViewModel( private val statisticsUpdater: StatisticsUpdater, @@ -1832,3 +1841,118 @@ class BrowserTabViewModel( private const val ONE_HOUR_IN_MS = 3_600_000 } } + +@Module +@ContributesTo(AppObjectGraph::class) +class BrowserTabViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideBrowserTabViewModelFactory( + statisticsUpdater: StatisticsUpdater, + queryUrlConverter: QueryUrlConverter, + duckDuckGoUrlDetector: DuckDuckGoUrlDetector, + siteFactory: SiteFactory, + tabRepository: TabRepository, + userWhitelistDao: UserWhitelistDao, + networkLeaderboardDao: NetworkLeaderboardDao, + bookmarksDao: BookmarksDao, + fireproofWebsiteRepository: FireproofWebsiteRepository, + locationPermissionsRepository: LocationPermissionsRepository, + geoLocationPermissions: GeoLocationPermissions, + navigationAwareLoginDetector: NavigationAwareLoginDetector, + autoCompleteApi: AutoCompleteApi, + appSettingsPreferencesStore: SettingsDataStore, + longPressHandler: LongPressHandler, + webViewSessionStorage: WebViewSessionStorage, + specialUrlDetector: SpecialUrlDetector, + faviconManager: FaviconManager, + addToHomeCapabilityDetector: AddToHomeCapabilityDetector, + ctaViewModel: CtaViewModel, + searchCountDao: SearchCountDao, + pixel: Pixel, + dispatchers: DispatcherProvider = DefaultDispatcherProvider(), + userEventsStore: UserEventsStore, + notificationDao: NotificationDao, + useOurAppDetector: UseOurAppDetector, + variantManager: VariantManager, + fileDownloader: FileDownloader, + globalPrivacyControl: GlobalPrivacyControl, + fireproofDialogsEventHandler: FireproofDialogsEventHandler + ): ViewModelFactoryPlugin { + return BrowserTabViewModelFactory( + statisticsUpdater, + queryUrlConverter, + duckDuckGoUrlDetector, + siteFactory, + tabRepository, + userWhitelistDao, + networkLeaderboardDao, + bookmarksDao, + fireproofWebsiteRepository, + locationPermissionsRepository, + geoLocationPermissions, + navigationAwareLoginDetector, + autoCompleteApi, + appSettingsPreferencesStore, + longPressHandler, + webViewSessionStorage, + specialUrlDetector, + faviconManager, + addToHomeCapabilityDetector, + ctaViewModel, + searchCountDao, + pixel, + dispatchers, + userEventsStore, + notificationDao, + useOurAppDetector, + variantManager, + fileDownloader, + globalPrivacyControl, + fireproofDialogsEventHandler + ) + } +} + +private class BrowserTabViewModelFactory( + private val statisticsUpdater: StatisticsUpdater, + private val queryUrlConverter: OmnibarEntryConverter, + private val duckDuckGoUrlDetector: DuckDuckGoUrlDetector, + private val siteFactory: SiteFactory, + private val tabRepository: TabRepository, + private val userWhitelistDao: UserWhitelistDao, + private val networkLeaderboardDao: NetworkLeaderboardDao, + private val bookmarksDao: BookmarksDao, + private val fireproofWebsiteRepository: FireproofWebsiteRepository, + private val locationPermissionsRepository: LocationPermissionsRepository, + private val geoLocationPermissions: GeoLocationPermissions, + private val navigationAwareLoginDetector: NavigationAwareLoginDetector, + private val autoComplete: AutoComplete, + private val appSettingsPreferencesStore: SettingsDataStore, + private val longPressHandler: LongPressHandler, + private val webViewSessionStorage: WebViewSessionStorage, + private val specialUrlDetector: SpecialUrlDetector, + private val faviconManager: FaviconManager, + private val addToHomeCapabilityDetector: AddToHomeCapabilityDetector, + private val ctaViewModel: CtaViewModel, + private val searchCountDao: SearchCountDao, + private val pixel: Pixel, + private val dispatchers: DispatcherProvider = DefaultDispatcherProvider(), + private val userEventsStore: UserEventsStore, + private val notificationDao: NotificationDao, + private val useOurAppDetector: UseOurAppDetector, + private val variantManager: VariantManager, + private val fileDownloader: FileDownloader, + private val globalPrivacyControl: GlobalPrivacyControl, + private val fireproofDialogsEventHandler: FireproofDialogsEventHandler +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(BrowserTabViewModel::class.java) -> BrowserTabViewModel(statisticsUpdater, queryUrlConverter, duckDuckGoUrlDetector, siteFactory, tabRepository, userWhitelistDao, networkLeaderboardDao, bookmarksDao, fireproofWebsiteRepository, locationPermissionsRepository, geoLocationPermissions, navigationAwareLoginDetector, autoComplete, appSettingsPreferencesStore, longPressHandler, webViewSessionStorage, specialUrlDetector, faviconManager, addToHomeCapabilityDetector, ctaViewModel, searchCountDao, pixel, dispatchers, userEventsStore, notificationDao, useOurAppDetector, variantManager, fileDownloader, globalPrivacyControl, fireproofDialogsEventHandler) as T + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserViewModel.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserViewModel.kt index 84bae806e0fc..e2a713f83b29 100644 --- a/app/src/main/java/com/duckduckgo/app/browser/BrowserViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserViewModel.kt @@ -24,6 +24,7 @@ import androidx.lifecycle.ViewModel import com.duckduckgo.app.browser.BrowserViewModel.Command.DisplayMessage import com.duckduckgo.app.browser.BrowserViewModel.Command.Refresh import com.duckduckgo.app.browser.omnibar.OmnibarEntryConverter +import com.duckduckgo.app.browser.omnibar.QueryUrlConverter import com.duckduckgo.app.browser.rating.ui.AppEnjoymentDialogFragment import com.duckduckgo.app.browser.rating.ui.GiveFeedbackDialogFragment import com.duckduckgo.app.browser.rating.ui.RateAppDialogFragment @@ -32,6 +33,7 @@ import com.duckduckgo.app.global.ApplicationClearDataState import com.duckduckgo.app.global.DefaultDispatcherProvider import com.duckduckgo.app.global.DispatcherProvider import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.global.rating.AppEnjoymentPromptEmitter import com.duckduckgo.app.global.rating.AppEnjoymentPromptOptions import com.duckduckgo.app.global.rating.AppEnjoymentUserEventRecorder @@ -41,10 +43,16 @@ import com.duckduckgo.app.privacy.ui.PrivacyDashboardActivity.Companion.RELOAD_R import com.duckduckgo.app.statistics.pixels.Pixel import com.duckduckgo.app.tabs.model.TabEntity import com.duckduckgo.app.tabs.model.TabRepository +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import timber.log.Timber +import javax.inject.Singleton import kotlin.coroutines.CoroutineContext class BrowserViewModel( @@ -231,3 +239,43 @@ class BrowserViewModel( } } } + +@Module +@ContributesTo(AppObjectGraph::class) +class BrowserViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideBrowserViewModelFactory( + tabRepository: TabRepository, + queryUrlConverter: QueryUrlConverter, + dataClearer: DataClearer, + appEnjoymentPromptEmitter: AppEnjoymentPromptEmitter, + appEnjoymentUserEventRecorder: AppEnjoymentUserEventRecorder, + dispatchers: DispatcherProvider = DefaultDispatcherProvider(), + pixel: Pixel, + useOurAppDetector: UseOurAppDetector + ): ViewModelFactoryPlugin { + return BrowserViewModelFactory(tabRepository, queryUrlConverter, dataClearer, appEnjoymentPromptEmitter, appEnjoymentUserEventRecorder, dispatchers, pixel, useOurAppDetector) + } +} + +private class BrowserViewModelFactory( + val tabRepository: TabRepository, + val queryUrlConverter: OmnibarEntryConverter, + val dataClearer: DataClearer, + val appEnjoymentPromptEmitter: AppEnjoymentPromptEmitter, + val appEnjoymentUserEventRecorder: AppEnjoymentUserEventRecorder, + val dispatchers: DispatcherProvider = DefaultDispatcherProvider(), + val pixel: Pixel, + val useOurAppDetector: UseOurAppDetector +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(BrowserViewModel::class.java) -> BrowserViewModel(tabRepository, queryUrlConverter, dataClearer, appEnjoymentPromptEmitter, appEnjoymentUserEventRecorder, dispatchers, pixel, useOurAppDetector) as T + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/feedback/ui/common/FeedbackViewModel.kt b/app/src/main/java/com/duckduckgo/app/feedback/ui/common/FeedbackViewModel.kt index 2f7016c5b358..87a46146d551 100644 --- a/app/src/main/java/com/duckduckgo/app/feedback/ui/common/FeedbackViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/feedback/ui/common/FeedbackViewModel.kt @@ -25,12 +25,19 @@ import com.duckduckgo.app.feedback.ui.negative.FeedbackType import com.duckduckgo.app.feedback.ui.negative.FeedbackType.MainReason import com.duckduckgo.app.feedback.ui.negative.FeedbackType.SubReason import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.playstore.PlayStoreUtils +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import timber.log.Timber +import javax.inject.Singleton class FeedbackViewModel(private val playStoreUtils: PlayStoreUtils, private val feedbackSubmitter: FeedbackSubmitter) : ViewModel() { @@ -282,3 +289,31 @@ data class UpdateViewCommand( val mainReason: MainReason? = null, val subReason: SubReason? = null ) + +@Module +@ContributesTo(AppObjectGraph::class) +class FeedbackViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideFeedbackViewModelFactory( + playStoreUtils: PlayStoreUtils, + feedbackSubmitter: FeedbackSubmitter + ): ViewModelFactoryPlugin { + return FeedbackViewModelFactory(playStoreUtils, feedbackSubmitter) + } +} + +private class FeedbackViewModelFactory( + private val playStoreUtils: PlayStoreUtils, + private val feedbackSubmitter: FeedbackSubmitter +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(FeedbackViewModel::class.java) -> (FeedbackViewModel(playStoreUtils, feedbackSubmitter) as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/feedback/ui/initial/InitialFeedbackFragmentViewModel.kt b/app/src/main/java/com/duckduckgo/app/feedback/ui/initial/InitialFeedbackFragmentViewModel.kt index 39f4084ee2ed..f247b4a33aab 100644 --- a/app/src/main/java/com/duckduckgo/app/feedback/ui/initial/InitialFeedbackFragmentViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/feedback/ui/initial/InitialFeedbackFragmentViewModel.kt @@ -19,6 +19,13 @@ package com.duckduckgo.app.feedback.ui.initial import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.duckduckgo.app.feedback.ui.common.ViewState +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet +import javax.inject.Singleton class InitialFeedbackFragmentViewModel : ViewModel() { @@ -39,3 +46,25 @@ class InitialFeedbackFragmentViewModel : ViewModel() { object UserCancelled : Command() } } + +@Module +@ContributesTo(AppObjectGraph::class) +class InitialFeedbackFragmentViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideInitialFeedbackFragmentViewModelFactory(): ViewModelFactoryPlugin { + return InitialFeedbackFragmentViewModelFactory() + } +} + +private class InitialFeedbackFragmentViewModelFactory() : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(InitialFeedbackFragmentViewModel::class.java) -> (InitialFeedbackFragmentViewModel() as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/feedback/ui/negative/brokensite/BrokenSiteNegativeFeedbackViewModel.kt b/app/src/main/java/com/duckduckgo/app/feedback/ui/negative/brokensite/BrokenSiteNegativeFeedbackViewModel.kt index 643bc677f8ed..67fc04a94bbc 100644 --- a/app/src/main/java/com/duckduckgo/app/feedback/ui/negative/brokensite/BrokenSiteNegativeFeedbackViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/feedback/ui/negative/brokensite/BrokenSiteNegativeFeedbackViewModel.kt @@ -18,6 +18,13 @@ package com.duckduckgo.app.feedback.ui.negative.brokensite import androidx.lifecycle.ViewModel import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet +import javax.inject.Singleton class BrokenSiteNegativeFeedbackViewModel : ViewModel() { @@ -32,3 +39,25 @@ class BrokenSiteNegativeFeedbackViewModel : ViewModel() { object Exit : Command() } } + +@Module +@ContributesTo(AppObjectGraph::class) +class BrokenSiteNegativeFeedbackViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideBrokenSiteNegativeFeedbackViewModelFactory(): ViewModelFactoryPlugin { + return BrokenSiteNegativeFeedbackViewModelFactory() + } +} + +private class BrokenSiteNegativeFeedbackViewModelFactory() : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(BrokenSiteNegativeFeedbackViewModel::class.java) -> (BrokenSiteNegativeFeedbackViewModel() as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/feedback/ui/negative/openended/ShareOpenEndedNegativeFeedbackViewModel.kt b/app/src/main/java/com/duckduckgo/app/feedback/ui/negative/openended/ShareOpenEndedNegativeFeedbackViewModel.kt index 8b9e7c93fd12..5161da230abe 100644 --- a/app/src/main/java/com/duckduckgo/app/feedback/ui/negative/openended/ShareOpenEndedNegativeFeedbackViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/feedback/ui/negative/openended/ShareOpenEndedNegativeFeedbackViewModel.kt @@ -20,6 +20,13 @@ import androidx.lifecycle.ViewModel import com.duckduckgo.app.feedback.ui.negative.FeedbackType.MainReason import com.duckduckgo.app.feedback.ui.negative.FeedbackType.SubReason import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet +import javax.inject.Singleton class ShareOpenEndedNegativeFeedbackViewModel : ViewModel() { @@ -39,3 +46,25 @@ class ShareOpenEndedNegativeFeedbackViewModel : ViewModel() { object Exit : Command() } } + +@Module +@ContributesTo(AppObjectGraph::class) +class ShareOpenEndedNegativeFeedbackViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideShareOpenEndedNegativeFeedbackViewModelFactory(): ViewModelFactoryPlugin { + return ShareOpenEndedNegativeFeedbackViewModelFactory() + } +} + +private class ShareOpenEndedNegativeFeedbackViewModelFactory() : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(ShareOpenEndedNegativeFeedbackViewModel::class.java) -> (ShareOpenEndedNegativeFeedbackViewModel() as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/feedback/ui/positive/initial/PositiveFeedbackLandingViewModel.kt b/app/src/main/java/com/duckduckgo/app/feedback/ui/positive/initial/PositiveFeedbackLandingViewModel.kt index 8a4b72fb89ac..7f7a135f610e 100644 --- a/app/src/main/java/com/duckduckgo/app/feedback/ui/positive/initial/PositiveFeedbackLandingViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/feedback/ui/positive/initial/PositiveFeedbackLandingViewModel.kt @@ -18,6 +18,13 @@ package com.duckduckgo.app.feedback.ui.positive.initial import androidx.lifecycle.ViewModel import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet +import javax.inject.Singleton class PositiveFeedbackLandingViewModel : ViewModel() { @@ -43,3 +50,25 @@ sealed class Command { object Exit : Command() object LaunchShareFeedbackPage : Command() } + +@Module +@ContributesTo(AppObjectGraph::class) +class PositiveFeedbackLandingViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun providePositiveFeedbackLandingViewModelFactory(): ViewModelFactoryPlugin { + return PositiveFeedbackLandingViewModelFactory() + } +} + +private class PositiveFeedbackLandingViewModelFactory() : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(PositiveFeedbackLandingViewModel::class.java) -> (PositiveFeedbackLandingViewModel() as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/fire/fireproofwebsite/ui/FireproofWebsitesViewModel.kt b/app/src/main/java/com/duckduckgo/app/fire/fireproofwebsite/ui/FireproofWebsitesViewModel.kt index d7bffa002944..1ebbeec4dcbc 100644 --- a/app/src/main/java/com/duckduckgo/app/fire/fireproofwebsite/ui/FireproofWebsitesViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/fire/fireproofwebsite/ui/FireproofWebsitesViewModel.kt @@ -25,10 +25,17 @@ import com.duckduckgo.app.global.DispatcherProvider import com.duckduckgo.app.global.SingleLiveEvent import com.duckduckgo.app.global.events.db.UserEventKey import com.duckduckgo.app.global.events.db.UserEventsStore +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.settings.db.SettingsDataStore import com.duckduckgo.app.statistics.pixels.Pixel import com.duckduckgo.app.statistics.pixels.Pixel.PixelName.* +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import kotlinx.coroutines.launch +import javax.inject.Singleton class FireproofWebsitesViewModel( private val fireproofWebsiteRepository: FireproofWebsiteRepository, @@ -103,3 +110,37 @@ class FireproofWebsitesViewModel( _viewState.value = _viewState.value?.copy(loginDetectionEnabled = enabled) } } + +@Module +@ContributesTo(AppObjectGraph::class) +class FireproofWebsitesViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideFireproofWebsitesViewModelFactory( + fireproofWebsiteRepository: FireproofWebsiteRepository, + dispatcherProvider: DispatcherProvider, + pixel: Pixel, + settingsDataStore: SettingsDataStore, + userEventsStore: UserEventsStore + ): ViewModelFactoryPlugin { + return FireproofWebsitesViewModelFactory(fireproofWebsiteRepository, dispatcherProvider, pixel, settingsDataStore, userEventsStore) + } +} + +private class FireproofWebsitesViewModelFactory( + private val fireproofWebsiteRepository: FireproofWebsiteRepository, + private val dispatcherProvider: DispatcherProvider, + private val pixel: Pixel, + private val settingsDataStore: SettingsDataStore, + private val userEventsStore: UserEventsStore +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(FireproofWebsitesViewModel::class.java) -> (FireproofWebsitesViewModel(fireproofWebsiteRepository, dispatcherProvider, pixel, settingsDataStore, userEventsStore) as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/global/ViewModelFactory.kt b/app/src/main/java/com/duckduckgo/app/global/ViewModelFactory.kt index c0edcbba70e9..378c93a3a555 100644 --- a/app/src/main/java/com/duckduckgo/app/global/ViewModelFactory.kt +++ b/app/src/main/java/com/duckduckgo/app/global/ViewModelFactory.kt @@ -18,247 +18,17 @@ package com.duckduckgo.app.global import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider -import com.duckduckgo.app.autocomplete.api.AutoCompleteApi -import com.duckduckgo.app.bookmarks.db.BookmarksDao -import com.duckduckgo.app.bookmarks.ui.BookmarksViewModel -import com.duckduckgo.app.brokensite.BrokenSiteViewModel -import com.duckduckgo.app.brokensite.api.BrokenSiteSender -import com.duckduckgo.app.browser.* -import com.duckduckgo.app.browser.addtohome.AddToHomeCapabilityDetector -import com.duckduckgo.app.browser.defaultbrowsing.DefaultBrowserDetector -import com.duckduckgo.app.browser.downloader.FileDownloader -import com.duckduckgo.app.browser.favicon.FaviconManager -import com.duckduckgo.app.browser.logindetection.FireproofDialogsEventHandler -import com.duckduckgo.app.browser.logindetection.NavigationAwareLoginDetector -import com.duckduckgo.app.browser.omnibar.QueryUrlConverter -import com.duckduckgo.app.browser.session.WebViewSessionStorage -import com.duckduckgo.app.cta.db.DismissedCtaDao -import com.duckduckgo.app.cta.ui.CtaViewModel -import com.duckduckgo.app.feedback.api.FeedbackSubmitter -import com.duckduckgo.app.feedback.ui.common.FeedbackViewModel -import com.duckduckgo.app.feedback.ui.initial.InitialFeedbackFragmentViewModel -import com.duckduckgo.app.feedback.ui.negative.brokensite.BrokenSiteNegativeFeedbackViewModel -import com.duckduckgo.app.feedback.ui.negative.openended.ShareOpenEndedNegativeFeedbackViewModel -import com.duckduckgo.app.feedback.ui.positive.initial.PositiveFeedbackLandingViewModel -import com.duckduckgo.app.fire.FireAnimationLoader -import com.duckduckgo.app.fire.DataClearer -import com.duckduckgo.app.fire.fireproofwebsite.data.FireproofWebsiteRepository -import com.duckduckgo.app.fire.fireproofwebsite.ui.FireproofWebsitesViewModel -import com.duckduckgo.app.global.install.AppInstallStore -import com.duckduckgo.app.global.model.SiteFactory -import com.duckduckgo.app.global.rating.AppEnjoymentPromptEmitter -import com.duckduckgo.app.global.rating.AppEnjoymentUserEventRecorder -import com.duckduckgo.app.global.events.db.UserEventsStore -import com.duckduckgo.app.global.useourapp.UseOurAppDetector -import com.duckduckgo.app.globalprivacycontrol.GlobalPrivacyControl -import com.duckduckgo.app.globalprivacycontrol.ui.GlobalPrivacyControlViewModel -import com.duckduckgo.app.icon.api.IconModifier -import com.duckduckgo.app.icon.ui.ChangeIconViewModel -import com.duckduckgo.app.launch.LaunchViewModel -import com.duckduckgo.app.notification.db.NotificationDao -import com.duckduckgo.app.location.GeoLocationPermissions -import com.duckduckgo.app.location.data.LocationPermissionsRepository -import com.duckduckgo.app.location.ui.LocationPermissionsViewModel -import com.duckduckgo.app.onboarding.store.UserStageStore -import com.duckduckgo.app.onboarding.ui.OnboardingPageManager -import com.duckduckgo.app.onboarding.ui.OnboardingViewModel -import com.duckduckgo.app.onboarding.ui.page.DefaultBrowserPageViewModel -import com.duckduckgo.app.playstore.PlayStoreUtils -import com.duckduckgo.app.privacy.db.NetworkLeaderboardDao -import com.duckduckgo.app.privacy.db.UserWhitelistDao -import com.duckduckgo.app.privacy.ui.* -import com.duckduckgo.app.referral.AppInstallationReferrerStateListener -import com.duckduckgo.app.settings.SettingsViewModel -import com.duckduckgo.app.settings.db.SettingsDataStore -import com.duckduckgo.app.statistics.VariantManager -import com.duckduckgo.app.statistics.api.StatisticsUpdater -import com.duckduckgo.app.statistics.pixels.Pixel -import com.duckduckgo.app.statistics.store.StatisticsDataStore -import com.duckduckgo.app.survey.db.SurveyDao -import com.duckduckgo.app.survey.ui.SurveyViewModel -import com.duckduckgo.app.systemsearch.DeviceAppLookup -import com.duckduckgo.app.systemsearch.SystemSearchViewModel -import com.duckduckgo.app.tabs.model.TabRepository -import com.duckduckgo.app.tabs.ui.TabSwitcherViewModel -import com.duckduckgo.app.usage.search.SearchCountDao -import com.duckduckgo.app.widget.ui.AddWidgetInstructionsViewModel +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPluginPoint import javax.inject.Inject -@Suppress("UNCHECKED_CAST") class ViewModelFactory @Inject constructor( - private val statisticsUpdater: StatisticsUpdater, - private val statisticsStore: StatisticsDataStore, - private val userStageStore: UserStageStore, - private val appInstallStore: AppInstallStore, - private val queryUrlConverter: QueryUrlConverter, - private val duckDuckGoUrlDetector: DuckDuckGoUrlDetector, - private val tabRepository: TabRepository, - private val siteFactory: SiteFactory, - private val userWhitelistDao: UserWhitelistDao, - private val networkLeaderboardDao: NetworkLeaderboardDao, - private val bookmarksDao: BookmarksDao, - private val fireproofWebsiteRepository: FireproofWebsiteRepository, - private val locationPermissionsRepository: LocationPermissionsRepository, - private val geoLocationPermissions: GeoLocationPermissions, - private val navigationAwareLoginDetector: NavigationAwareLoginDetector, - private val surveyDao: SurveyDao, - private val autoCompleteApi: AutoCompleteApi, - private val deviceAppLookup: DeviceAppLookup, - private val appSettingsPreferencesStore: SettingsDataStore, - private val webViewLongPressHandler: LongPressHandler, - private val defaultBrowserDetector: DefaultBrowserDetector, - private val variantManager: VariantManager, - private val brokenSiteSender: BrokenSiteSender, - private val webViewSessionStorage: WebViewSessionStorage, - private val specialUrlDetector: SpecialUrlDetector, - private val faviconManager: FaviconManager, - private val addToHomeCapabilityDetector: AddToHomeCapabilityDetector, - private val pixel: Pixel, - private val dataClearer: DataClearer, - private val ctaViewModel: CtaViewModel, - private val appEnjoymentPromptEmitter: AppEnjoymentPromptEmitter, - private val searchCountDao: SearchCountDao, - private val appEnjoymentUserEventRecorder: AppEnjoymentUserEventRecorder, - private val playStoreUtils: PlayStoreUtils, - private val feedbackSubmitter: FeedbackSubmitter, - private val onboardingPageManager: OnboardingPageManager, - private val appInstallationReferrerStateListener: AppInstallationReferrerStateListener, - private val appIconModifier: IconModifier, - private val userEventsStore: UserEventsStore, - private val notificationDao: NotificationDao, - private val userOurAppDetector: UseOurAppDetector, - private val dismissedCtaDao: DismissedCtaDao, - private val fileDownloader: FileDownloader, - private val dispatcherProvider: DispatcherProvider, - private val fireAnimationLoader: FireAnimationLoader, - private val globalPrivacyControl: GlobalPrivacyControl, - private val fireproofDialogsEventHandler: FireproofDialogsEventHandler + private val viewModelFactoryPluginPoint: ViewModelFactoryPluginPoint ) : ViewModelProvider.NewInstanceFactory() { - override fun create(modelClass: Class) = - with(modelClass) { - when { - isAssignableFrom(LaunchViewModel::class.java) -> LaunchViewModel(userStageStore, appInstallationReferrerStateListener) - isAssignableFrom(SystemSearchViewModel::class.java) -> SystemSearchViewModel(userStageStore, autoCompleteApi, deviceAppLookup, pixel) - isAssignableFrom(OnboardingViewModel::class.java) -> onboardingViewModel() - isAssignableFrom(BrowserViewModel::class.java) -> browserViewModel() - isAssignableFrom(BrowserTabViewModel::class.java) -> browserTabViewModel() - isAssignableFrom(TabSwitcherViewModel::class.java) -> TabSwitcherViewModel(tabRepository, webViewSessionStorage) - isAssignableFrom(PrivacyDashboardViewModel::class.java) -> privacyDashboardViewModel() - isAssignableFrom(ScorecardViewModel::class.java) -> ScorecardViewModel(userWhitelistDao) - isAssignableFrom(TrackerNetworksViewModel::class.java) -> TrackerNetworksViewModel() - isAssignableFrom(PrivacyPracticesViewModel::class.java) -> PrivacyPracticesViewModel() - isAssignableFrom(WhitelistViewModel::class.java) -> WhitelistViewModel(userWhitelistDao) - isAssignableFrom(FeedbackViewModel::class.java) -> FeedbackViewModel(playStoreUtils, feedbackSubmitter) - isAssignableFrom(BrokenSiteViewModel::class.java) -> BrokenSiteViewModel(pixel, brokenSiteSender) - isAssignableFrom(SurveyViewModel::class.java) -> SurveyViewModel(surveyDao, statisticsStore, appInstallStore) - isAssignableFrom(AddWidgetInstructionsViewModel::class.java) -> AddWidgetInstructionsViewModel() - isAssignableFrom(SettingsViewModel::class.java) -> settingsViewModel() - isAssignableFrom(BookmarksViewModel::class.java) -> BookmarksViewModel(bookmarksDao, faviconManager, dispatcherProvider) - isAssignableFrom(InitialFeedbackFragmentViewModel::class.java) -> InitialFeedbackFragmentViewModel() - isAssignableFrom(PositiveFeedbackLandingViewModel::class.java) -> PositiveFeedbackLandingViewModel() - isAssignableFrom(ShareOpenEndedNegativeFeedbackViewModel::class.java) -> ShareOpenEndedNegativeFeedbackViewModel() - isAssignableFrom(BrokenSiteNegativeFeedbackViewModel::class.java) -> BrokenSiteNegativeFeedbackViewModel() - isAssignableFrom(DefaultBrowserPageViewModel::class.java) -> defaultBrowserPage() - isAssignableFrom(ChangeIconViewModel::class.java) -> changeAppIconViewModel() - isAssignableFrom(FireproofWebsitesViewModel::class.java) -> fireproofWebsiteViewModel() - isAssignableFrom(LocationPermissionsViewModel::class.java) -> locationPermissionsViewModel() - isAssignableFrom(GlobalPrivacyControlViewModel::class.java) -> globalPrivacyControlViewModel() + override fun create(modelClass: Class): T { + val viewModel = viewModelFactoryPluginPoint.getPlugins().mapNotNull { it.create(modelClass) }.first() as T + ?: throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}") - else -> throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}") - } - } as T - - private fun defaultBrowserPage() = DefaultBrowserPageViewModel(defaultBrowserDetector, pixel, appInstallStore) - - private fun onboardingViewModel() = OnboardingViewModel(userStageStore, onboardingPageManager, dispatcherProvider) - - private fun settingsViewModel(): SettingsViewModel { - return SettingsViewModel( - appSettingsPreferencesStore, - defaultBrowserDetector, - variantManager, - fireAnimationLoader, - pixel - ) - } - - private fun privacyDashboardViewModel(): PrivacyDashboardViewModel { - return PrivacyDashboardViewModel( - userWhitelistDao, - networkLeaderboardDao, - pixel - ) - } - - private fun browserViewModel(): BrowserViewModel { - return BrowserViewModel( - tabRepository = tabRepository, - queryUrlConverter = queryUrlConverter, - dataClearer = dataClearer, - appEnjoymentPromptEmitter = appEnjoymentPromptEmitter, - appEnjoymentUserEventRecorder = appEnjoymentUserEventRecorder, - useOurAppDetector = userOurAppDetector, - pixel = pixel - ) + return viewModel } - - private fun browserTabViewModel(): ViewModel = BrowserTabViewModel( - statisticsUpdater = statisticsUpdater, - queryUrlConverter = queryUrlConverter, - duckDuckGoUrlDetector = duckDuckGoUrlDetector, - siteFactory = siteFactory, - tabRepository = tabRepository, - userWhitelistDao = userWhitelistDao, - networkLeaderboardDao = networkLeaderboardDao, - bookmarksDao = bookmarksDao, - fireproofWebsiteRepository = fireproofWebsiteRepository, - locationPermissionsRepository = locationPermissionsRepository, - geoLocationPermissions = geoLocationPermissions, - navigationAwareLoginDetector = navigationAwareLoginDetector, - autoComplete = autoCompleteApi, - appSettingsPreferencesStore = appSettingsPreferencesStore, - longPressHandler = webViewLongPressHandler, - webViewSessionStorage = webViewSessionStorage, - specialUrlDetector = specialUrlDetector, - faviconManager = faviconManager, - addToHomeCapabilityDetector = addToHomeCapabilityDetector, - ctaViewModel = ctaViewModel, - searchCountDao = searchCountDao, - pixel = pixel, - userEventsStore = userEventsStore, - notificationDao = notificationDao, - useOurAppDetector = userOurAppDetector, - variantManager = variantManager, - fileDownloader = fileDownloader, - globalPrivacyControl = globalPrivacyControl, - fireproofDialogsEventHandler = fireproofDialogsEventHandler - ) - - private fun changeAppIconViewModel() = - ChangeIconViewModel(settingsDataStore = appSettingsPreferencesStore, appIconModifier = appIconModifier, pixel = pixel) - - private fun fireproofWebsiteViewModel() = - FireproofWebsitesViewModel( - fireproofWebsiteRepository = fireproofWebsiteRepository, - dispatcherProvider = dispatcherProvider, - pixel = pixel, - settingsDataStore = appSettingsPreferencesStore, - userEventsStore = userEventsStore - ) - - private fun locationPermissionsViewModel() = - LocationPermissionsViewModel( - locationPermissionsRepository = locationPermissionsRepository, - geoLocationPermissions = geoLocationPermissions, - dispatcherProvider = dispatcherProvider, - settingsDataStore = appSettingsPreferencesStore, - pixel = pixel - ) - - private fun globalPrivacyControlViewModel() = - GlobalPrivacyControlViewModel( - settingsDataStore = appSettingsPreferencesStore, - pixel = pixel - ) } diff --git a/app/src/main/java/com/duckduckgo/app/globalprivacycontrol/ui/GlobalPrivacyControlViewModel.kt b/app/src/main/java/com/duckduckgo/app/globalprivacycontrol/ui/GlobalPrivacyControlViewModel.kt index 82162b1e1edc..e1bcf452f886 100644 --- a/app/src/main/java/com/duckduckgo/app/globalprivacycontrol/ui/GlobalPrivacyControlViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/globalprivacycontrol/ui/GlobalPrivacyControlViewModel.kt @@ -18,9 +18,16 @@ package com.duckduckgo.app.globalprivacycontrol.ui import androidx.lifecycle.* import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.settings.db.SettingsDataStore import com.duckduckgo.app.statistics.pixels.Pixel import com.duckduckgo.app.statistics.pixels.Pixel.PixelName.* +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet +import javax.inject.Singleton class GlobalPrivacyControlViewModel( private val pixel: Pixel, @@ -61,3 +68,31 @@ class GlobalPrivacyControlViewModel( const val LEARN_MORE_URL = "https://duckduckgo.com/global-privacy-control-learn-more" } } + +@Module +@ContributesTo(AppObjectGraph::class) +class GlobalPrivacyControlViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideGlobalPrivacyControlViewModelFactory( + pixel: Pixel, + settingsDataStore: SettingsDataStore + ): ViewModelFactoryPlugin { + return GlobalPrivacyControlViewModelFactory(pixel, settingsDataStore) + } +} + +private class GlobalPrivacyControlViewModelFactory( + private val pixel: Pixel, + private val settingsDataStore: SettingsDataStore +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(GlobalPrivacyControlViewModel::class.java) -> (GlobalPrivacyControlViewModel(pixel, settingsDataStore) as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/icon/ui/ChangeIconViewModel.kt b/app/src/main/java/com/duckduckgo/app/icon/ui/ChangeIconViewModel.kt index 577b16f663da..c07a32ab5c0b 100644 --- a/app/src/main/java/com/duckduckgo/app/icon/ui/ChangeIconViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/icon/ui/ChangeIconViewModel.kt @@ -19,11 +19,18 @@ package com.duckduckgo.app.icon.ui import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.icon.api.AppIcon import com.duckduckgo.app.icon.api.IconModifier import com.duckduckgo.app.settings.db.SettingsDataStore import com.duckduckgo.app.statistics.pixels.Pixel +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import javax.inject.Inject +import javax.inject.Singleton class ChangeIconViewModel @Inject constructor( private val settingsDataStore: SettingsDataStore, @@ -72,5 +79,34 @@ class ChangeIconViewModel @Inject constructor( appIconModifier.changeIcon(previousIcon, viewData.appIcon) command.value = Command.IconChanged } +} +@Module +@ContributesTo(AppObjectGraph::class) +class ChangeIconViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideChangeIconViewModelFactory( + settingsDataStore: SettingsDataStore, + appIconModifier: IconModifier, + pixel: Pixel + ): ViewModelFactoryPlugin { + return ChangeIconViewModelFactory(settingsDataStore, appIconModifier, pixel) + } +} + +private class ChangeIconViewModelFactory( + private val settingsDataStore: SettingsDataStore, + private val appIconModifier: IconModifier, + private val pixel: Pixel +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(ChangeIconViewModel::class.java) -> (ChangeIconViewModel(settingsDataStore, appIconModifier, pixel) as T) + else -> null + } + } + } } diff --git a/app/src/main/java/com/duckduckgo/app/launch/LaunchViewModel.kt b/app/src/main/java/com/duckduckgo/app/launch/LaunchViewModel.kt index ed5265de0403..a2af53fed089 100644 --- a/app/src/main/java/com/duckduckgo/app/launch/LaunchViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/launch/LaunchViewModel.kt @@ -18,12 +18,19 @@ package com.duckduckgo.app.launch import androidx.lifecycle.ViewModel import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.onboarding.store.UserStageStore import com.duckduckgo.app.onboarding.store.isNewUser import com.duckduckgo.app.referral.AppInstallationReferrerStateListener import com.duckduckgo.app.referral.AppInstallationReferrerStateListener.Companion.MAX_REFERRER_WAIT_TIME_MS +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import kotlinx.coroutines.withTimeoutOrNull import timber.log.Timber +import javax.inject.Singleton class LaunchViewModel( private val userStageStore: UserStageStore, @@ -59,3 +66,31 @@ class LaunchViewModel( Timber.d("Waited ${System.currentTimeMillis() - startTime}ms for referrer") } } + +@Module +@ContributesTo(AppObjectGraph::class) +class LaunchViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideLaunchViewModelFactory( + userStageStore: UserStageStore, + appInstallationReferrerStateListener: AppInstallationReferrerStateListener + ): ViewModelFactoryPlugin { + return LaunchViewModelFactory(userStageStore, appInstallationReferrerStateListener) + } +} + +private class LaunchViewModelFactory( + private val userStageStore: UserStageStore, + private val appInstallationReferrerStateListener: AppInstallationReferrerStateListener +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(LaunchViewModel::class.java) -> (LaunchViewModel(userStageStore, appInstallationReferrerStateListener) as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/location/ui/LocationPermissionsViewModel.kt b/app/src/main/java/com/duckduckgo/app/location/ui/LocationPermissionsViewModel.kt index f72d47f82750..f5ff366e9f7b 100644 --- a/app/src/main/java/com/duckduckgo/app/location/ui/LocationPermissionsViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/location/ui/LocationPermissionsViewModel.kt @@ -20,13 +20,20 @@ import androidx.lifecycle.* import androidx.lifecycle.Observer import com.duckduckgo.app.global.DispatcherProvider import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.location.GeoLocationPermissions import com.duckduckgo.app.location.data.LocationPermissionEntity import com.duckduckgo.app.location.data.LocationPermissionType import com.duckduckgo.app.location.data.LocationPermissionsRepository import com.duckduckgo.app.settings.db.SettingsDataStore import com.duckduckgo.app.statistics.pixels.Pixel +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import kotlinx.coroutines.launch +import javax.inject.Singleton class LocationPermissionsViewModel( private val locationPermissionsRepository: LocationPermissionsRepository, @@ -129,3 +136,37 @@ class LocationPermissionsViewModel( } } } + +@Module +@ContributesTo(AppObjectGraph::class) +class LocationPermissionsViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideLocationPermissionsViewModelFactory( + locationPermissionsRepository: LocationPermissionsRepository, + geoLocationPermissions: GeoLocationPermissions, + dispatcherProvider: DispatcherProvider, + settingsDataStore: SettingsDataStore, + pixel: Pixel + ): ViewModelFactoryPlugin { + return LocationPermissionsViewModelFactory(locationPermissionsRepository, geoLocationPermissions, dispatcherProvider, settingsDataStore, pixel) + } +} + +private class LocationPermissionsViewModelFactory( + private val locationPermissionsRepository: LocationPermissionsRepository, + private val geoLocationPermissions: GeoLocationPermissions, + private val dispatcherProvider: DispatcherProvider, + private val settingsDataStore: SettingsDataStore, + private val pixel: Pixel +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(LocationPermissionsViewModel::class.java) -> (LocationPermissionsViewModel(locationPermissionsRepository, geoLocationPermissions, dispatcherProvider, settingsDataStore, pixel) as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingViewModel.kt b/app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingViewModel.kt index 6468a9a72cea..1a6a02de403d 100644 --- a/app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/onboarding/ui/OnboardingViewModel.kt @@ -19,10 +19,17 @@ package com.duckduckgo.app.onboarding.ui import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.duckduckgo.app.global.DispatcherProvider +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.onboarding.store.AppStage import com.duckduckgo.app.onboarding.store.UserStageStore import com.duckduckgo.app.onboarding.ui.page.OnboardingPageFragment +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import kotlinx.coroutines.launch +import javax.inject.Singleton class OnboardingViewModel( private val userStageStore: UserStageStore, @@ -49,3 +56,33 @@ class OnboardingViewModel( } } } + +@Module +@ContributesTo(AppObjectGraph::class) +class OnboardingViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideOnboardingViewModelFactory( + userStageStore: UserStageStore, + pageLayoutManager: OnboardingPageManager, + dispatchers: DispatcherProvider + ): ViewModelFactoryPlugin { + return OnboardingViewModelFactory(userStageStore, pageLayoutManager, dispatchers) + } +} + +private class OnboardingViewModelFactory( + private val userStageStore: UserStageStore, + private val pageLayoutManager: OnboardingPageManager, + private val dispatchers: DispatcherProvider +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(OnboardingViewModel::class.java) -> (OnboardingViewModel(userStageStore, pageLayoutManager, dispatchers) as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/onboarding/ui/page/DefaultBrowserPageViewModel.kt b/app/src/main/java/com/duckduckgo/app/onboarding/ui/page/DefaultBrowserPageViewModel.kt index 2e5113345e15..0c1e34f51e70 100644 --- a/app/src/main/java/com/duckduckgo/app/onboarding/ui/page/DefaultBrowserPageViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/onboarding/ui/page/DefaultBrowserPageViewModel.kt @@ -21,7 +21,14 @@ import androidx.lifecycle.ViewModel import com.duckduckgo.app.browser.defaultbrowsing.DefaultBrowserDetector import com.duckduckgo.app.global.SingleLiveEvent import com.duckduckgo.app.global.install.AppInstallStore +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.statistics.pixels.Pixel +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet +import javax.inject.Singleton class DefaultBrowserPageViewModel( private val defaultBrowserDetector: DefaultBrowserDetector, @@ -193,3 +200,33 @@ class DefaultBrowserPageViewModel( const val DEFAULT_URL = "https://duckduckgo.com" } } + +@Module +@ContributesTo(AppObjectGraph::class) +class DefaultBrowserPageViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideDefaultBrowserPageViewModelFactory( + defaultBrowserDetector: DefaultBrowserDetector, + pixel: Pixel, + installStore: AppInstallStore + ): ViewModelFactoryPlugin { + return DefaultBrowserPageViewModelFactory(defaultBrowserDetector, pixel, installStore) + } +} + +private class DefaultBrowserPageViewModelFactory( + private val defaultBrowserDetector: DefaultBrowserDetector, + private val pixel: Pixel, + private val installStore: AppInstallStore +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(DefaultBrowserPageViewModel::class.java) -> (DefaultBrowserPageViewModel(defaultBrowserDetector, pixel, installStore) as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyDashboardViewModel.kt b/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyDashboardViewModel.kt index 62e7a9c256cd..966d7f2e3bde 100644 --- a/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyDashboardViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyDashboardViewModel.kt @@ -24,6 +24,7 @@ import com.duckduckgo.app.global.DispatcherProvider import com.duckduckgo.app.global.SingleLiveEvent import com.duckduckgo.app.global.model.Site import com.duckduckgo.app.global.model.domain +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.privacy.db.NetworkLeaderboardDao import com.duckduckgo.app.privacy.db.NetworkLeaderboardEntry import com.duckduckgo.app.privacy.db.UserWhitelistDao @@ -35,9 +36,15 @@ import com.duckduckgo.app.privacy.ui.PrivacyDashboardViewModel.Command.LaunchMan import com.duckduckgo.app.privacy.ui.PrivacyDashboardViewModel.Command.LaunchReportBrokenSite import com.duckduckgo.app.statistics.pixels.Pixel import com.duckduckgo.app.statistics.pixels.Pixel.PixelName.* +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import javax.inject.Singleton class PrivacyDashboardViewModel( private val userWhitelistDao: UserWhitelistDao, @@ -197,3 +204,33 @@ class PrivacyDashboardViewModel( private const val LEADERBOARD_MIN_DOMAINS_EXCLUSIVE = 30 } } + +@Module +@ContributesTo(AppObjectGraph::class) +class PrivacyDashboardViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun providePrivacyDashboardViewModelFactory( + userWhitelistDao: UserWhitelistDao, + networkLeaderboardDao: NetworkLeaderboardDao, + pixel: Pixel + ): ViewModelFactoryPlugin { + return PrivacyDashboardViewModelFactory(userWhitelistDao, networkLeaderboardDao, pixel) + } +} + +private class PrivacyDashboardViewModelFactory( + private val userWhitelistDao: UserWhitelistDao, + private val networkLeaderboardDao: NetworkLeaderboardDao, + private val pixel: Pixel +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(PrivacyDashboardViewModel::class.java) -> PrivacyDashboardViewModel(userWhitelistDao, networkLeaderboardDao, pixel) as T + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyPracticesViewModel.kt b/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyPracticesViewModel.kt index 36f62223c365..e84f820b5f6f 100644 --- a/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyPracticesViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/privacy/ui/PrivacyPracticesViewModel.kt @@ -20,8 +20,15 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.duckduckgo.app.global.model.Site import com.duckduckgo.app.global.model.domain +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.privacy.model.PrivacyPractices import com.duckduckgo.app.privacy.model.PrivacyPractices.Summary.UNKNOWN +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet +import javax.inject.Singleton class PrivacyPracticesViewModel : ViewModel() { @@ -60,3 +67,25 @@ class PrivacyPracticesViewModel : ViewModel() { ) } } + +@Module +@ContributesTo(AppObjectGraph::class) +class PrivacyPracticesViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun providePrivacyPracticesViewModelFactory(): ViewModelFactoryPlugin { + return PrivacyPracticesViewModelFactory() + } +} + +private class PrivacyPracticesViewModelFactory() : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(PrivacyPracticesViewModel::class.java) -> (PrivacyPracticesViewModel() as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/privacy/ui/ScorecardViewModel.kt b/app/src/main/java/com/duckduckgo/app/privacy/ui/ScorecardViewModel.kt index f954f34df179..1c88e22a8970 100644 --- a/app/src/main/java/com/duckduckgo/app/privacy/ui/ScorecardViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/privacy/ui/ScorecardViewModel.kt @@ -23,13 +23,20 @@ import com.duckduckgo.app.global.DefaultDispatcherProvider import com.duckduckgo.app.global.DispatcherProvider import com.duckduckgo.app.global.model.Site import com.duckduckgo.app.global.model.domain +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.privacy.db.UserWhitelistDao import com.duckduckgo.app.privacy.model.HttpsStatus import com.duckduckgo.app.privacy.model.PrivacyGrade import com.duckduckgo.app.privacy.model.PrivacyPractices import com.duckduckgo.app.privacy.model.PrivacyPractices.Summary.UNKNOWN +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import javax.inject.Singleton class ScorecardViewModel( private val userWhitelistDao: UserWhitelistDao, @@ -107,3 +114,27 @@ class ScorecardViewModel( } } } + +@Module +@ContributesTo(AppObjectGraph::class) +class ScorecardViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideScorecardViewModelFactory(userWhitelistDao: UserWhitelistDao): ViewModelFactoryPlugin { + return ScorecardViewModelFactory(userWhitelistDao) + } +} + +private class ScorecardViewModelFactory( + private val userWhitelistDao: UserWhitelistDao, +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(ScorecardViewModel::class.java) -> ScorecardViewModel(userWhitelistDao) as T + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/privacy/ui/TrackerNetworksViewModel.kt b/app/src/main/java/com/duckduckgo/app/privacy/ui/TrackerNetworksViewModel.kt index 6644b30abdb1..86b8449d838b 100644 --- a/app/src/main/java/com/duckduckgo/app/privacy/ui/TrackerNetworksViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/privacy/ui/TrackerNetworksViewModel.kt @@ -22,10 +22,17 @@ import androidx.lifecycle.ViewModel import com.duckduckgo.app.global.baseHost import com.duckduckgo.app.global.model.Site import com.duckduckgo.app.global.model.domain +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.trackerdetection.model.Entity import com.duckduckgo.app.trackerdetection.model.TdsEntity import com.duckduckgo.app.trackerdetection.model.TrackingEvent +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import java.util.* +import javax.inject.Singleton class TrackerNetworksViewModel : ViewModel() { @@ -85,3 +92,25 @@ class TrackerNetworksViewModel : ViewModel() { return emptyMap>().toSortedMap(comparator) } } + +@Module +@ContributesTo(AppObjectGraph::class) +class TrackerNetworksViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideTrackerNetworksViewModelFactory(): ViewModelFactoryPlugin { + return TrackerNetworksViewModelFactory() + } +} + +private class TrackerNetworksViewModelFactory() : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(TrackerNetworksViewModel::class.java) -> (TrackerNetworksViewModel() as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/privacy/ui/WhitelistViewModel.kt b/app/src/main/java/com/duckduckgo/app/privacy/ui/WhitelistViewModel.kt index d37c4f714ae6..eef477299a92 100644 --- a/app/src/main/java/com/duckduckgo/app/privacy/ui/WhitelistViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/privacy/ui/WhitelistViewModel.kt @@ -24,12 +24,19 @@ import com.duckduckgo.app.global.DefaultDispatcherProvider import com.duckduckgo.app.global.DispatcherProvider import com.duckduckgo.app.global.SingleLiveEvent import com.duckduckgo.app.global.UriString +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.privacy.db.UserWhitelistDao import com.duckduckgo.app.privacy.model.UserWhitelistedDomain import com.duckduckgo.app.privacy.ui.WhitelistViewModel.Command.* +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import javax.inject.Singleton class WhitelistViewModel( private val dao: UserWhitelistDao, @@ -118,3 +125,29 @@ class WhitelistViewModel( withContext(dispatchers.io()) { dao.delete(entry) } } } + +@Module +@ContributesTo(AppObjectGraph::class) +class WhitelistViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideWhitelistViewModelFactory( + dao: UserWhitelistDao + ): ViewModelFactoryPlugin { + return WhitelistViewModelFactory(dao) + } +} + +private class WhitelistViewModelFactory( + private val dao: UserWhitelistDao +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(WhitelistViewModel::class.java) -> (WhitelistViewModel(dao) as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/settings/SettingsViewModel.kt b/app/src/main/java/com/duckduckgo/app/settings/SettingsViewModel.kt index 2ec7a9f018b2..0ed48bb30e55 100644 --- a/app/src/main/java/com/duckduckgo/app/settings/SettingsViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/settings/SettingsViewModel.kt @@ -23,6 +23,7 @@ import com.duckduckgo.app.browser.defaultbrowsing.DefaultBrowserDetector import com.duckduckgo.app.fire.FireAnimationLoader import com.duckduckgo.app.global.DuckDuckGoTheme import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.icon.api.AppIcon import com.duckduckgo.app.settings.clear.ClearWhatOption import com.duckduckgo.app.settings.clear.ClearWhenOption @@ -34,8 +35,14 @@ import com.duckduckgo.app.statistics.pixels.Pixel import com.duckduckgo.app.statistics.pixels.Pixel.PixelName import com.duckduckgo.app.statistics.pixels.Pixel.PixelName.* import com.duckduckgo.app.statistics.pixels.Pixel.PixelParameter.FIRE_ANIMATION +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import timber.log.Timber import javax.inject.Inject +import javax.inject.Singleton class SettingsViewModel @Inject constructor( private val settingsDataStore: SettingsDataStore, @@ -236,3 +243,37 @@ class SettingsViewModel @Inject constructor( } } } + +@Module +@ContributesTo(AppObjectGraph::class) +class SettingsViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideSettingsViewModelFactory( + settingsDataStore: SettingsDataStore, + defaultWebBrowserCapability: DefaultBrowserDetector, + variantManager: VariantManager, + fireAnimationLoader: FireAnimationLoader, + pixel: Pixel + ): ViewModelFactoryPlugin { + return SettingsViewModelFactory(settingsDataStore, defaultWebBrowserCapability, variantManager, fireAnimationLoader, pixel) + } +} + +private class SettingsViewModelFactory( + private val settingsDataStore: SettingsDataStore, + private val defaultWebBrowserCapability: DefaultBrowserDetector, + private val variantManager: VariantManager, + private val fireAnimationLoader: FireAnimationLoader, + private val pixel: Pixel +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(SettingsViewModel::class.java) -> (SettingsViewModel(settingsDataStore, defaultWebBrowserCapability, variantManager, fireAnimationLoader, pixel) as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/survey/ui/SurveyViewModel.kt b/app/src/main/java/com/duckduckgo/app/survey/ui/SurveyViewModel.kt index 067ceaff508d..5743fb9b2e4e 100644 --- a/app/src/main/java/com/duckduckgo/app/survey/ui/SurveyViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/survey/ui/SurveyViewModel.kt @@ -26,12 +26,19 @@ import com.duckduckgo.app.global.DispatcherProvider import com.duckduckgo.app.global.SingleLiveEvent import com.duckduckgo.app.global.install.AppInstallStore import com.duckduckgo.app.global.install.daysInstalled +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.statistics.store.StatisticsDataStore import com.duckduckgo.app.survey.db.SurveyDao import com.duckduckgo.app.survey.model.Survey +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import javax.inject.Singleton class SurveyViewModel( private val surveyDao: SurveyDao, @@ -108,3 +115,33 @@ class SurveyViewModel( const val MODEL = "mo" } } + +@Module +@ContributesTo(AppObjectGraph::class) +class SurveyViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideSurveyViewModelFactory( + surveyDao: SurveyDao, + statisticsStore: StatisticsDataStore, + appInstallStore: AppInstallStore, + ): ViewModelFactoryPlugin { + return SurveyViewModelFactory(surveyDao, statisticsStore, appInstallStore) + } +} + +private class SurveyViewModelFactory( + private val surveyDao: SurveyDao, + private val statisticsStore: StatisticsDataStore, + private val appInstallStore: AppInstallStore +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(SurveyViewModel::class.java) -> (SurveyViewModel(surveyDao, statisticsStore, appInstallStore) as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/systemsearch/SystemSearchViewModel.kt b/app/src/main/java/com/duckduckgo/app/systemsearch/SystemSearchViewModel.kt index 09099411ca8f..a82a9dd197e5 100644 --- a/app/src/main/java/com/duckduckgo/app/systemsearch/SystemSearchViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/systemsearch/SystemSearchViewModel.kt @@ -21,15 +21,22 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.duckduckgo.app.autocomplete.api.AutoComplete import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteResult +import com.duckduckgo.app.autocomplete.api.AutoCompleteApi import com.duckduckgo.app.global.DefaultDispatcherProvider import com.duckduckgo.app.global.DispatcherProvider import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.onboarding.store.AppStage import com.duckduckgo.app.onboarding.store.UserStageStore import com.duckduckgo.app.onboarding.store.isNewUser import com.duckduckgo.app.statistics.pixels.Pixel import com.duckduckgo.app.statistics.pixels.Pixel.PixelName.* +import com.duckduckgo.di.scopes.AppObjectGraph import com.jakewharton.rxrelay2.PublishRelay +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable @@ -39,6 +46,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.launch import timber.log.Timber import java.util.concurrent.TimeUnit +import javax.inject.Singleton data class SystemSearchResult(val autocomplete: AutoCompleteResult, val deviceApps: List) @@ -250,3 +258,35 @@ class SystemSearchViewModel( private const val RESULTS_MAX_RESULTS_PER_GROUP = 4 } } + +@Module +@ContributesTo(AppObjectGraph::class) +class SystemSearchViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideSystemSearchViewModelFactory( + userStageStore: UserStageStore, + autoCompleteApi: AutoCompleteApi, + deviceAppLookup: DeviceAppLookup, + pixel: Pixel, + ): ViewModelFactoryPlugin { + return SystemSearchViewModelFactory(userStageStore, autoCompleteApi, deviceAppLookup, pixel) + } +} + +private class SystemSearchViewModelFactory( + private val userStageStore: UserStageStore, + private val autoComplete: AutoComplete, + private val deviceAppLookup: DeviceAppLookup, + private val pixel: Pixel +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(SystemSearchViewModel::class.java) -> (SystemSearchViewModel(userStageStore, autoComplete, deviceAppLookup, pixel) as T) + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherViewModel.kt b/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherViewModel.kt index 82ceb8ba1914..32c8ec6a99cb 100644 --- a/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherViewModel.kt @@ -24,8 +24,15 @@ import androidx.lifecycle.viewModelScope import com.duckduckgo.app.browser.R import com.duckduckgo.app.browser.session.WebViewSessionStorage import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.tabs.model.TabEntity import com.duckduckgo.app.tabs.model.TabRepository +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet +import javax.inject.Singleton class TabSwitcherViewModel(private val tabRepository: TabRepository, private val webViewSessionStorage: WebViewSessionStorage) : ViewModel() { @@ -72,3 +79,31 @@ class TabSwitcherViewModel(private val tabRepository: TabRepository, private val command.value = Command.Close } } + +@Module +@ContributesTo(AppObjectGraph::class) +class TabSwitcherViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideTabSwitcherViewModelFactory( + tabRepository: TabRepository, + webViewSessionStorage: WebViewSessionStorage + ): ViewModelFactoryPlugin { + return TabSwitcherViewModelFactory(tabRepository, webViewSessionStorage) + } +} + +private class TabSwitcherViewModelFactory( + private val tabRepository: TabRepository, + private val webViewSessionStorage: WebViewSessionStorage +) : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(TabSwitcherViewModel::class.java) -> TabSwitcherViewModel(tabRepository, webViewSessionStorage) as T + else -> null + } + } + } +} diff --git a/app/src/main/java/com/duckduckgo/app/widget/ui/AddWidgetInstructionsViewModel.kt b/app/src/main/java/com/duckduckgo/app/widget/ui/AddWidgetInstructionsViewModel.kt index 0d5db08e79c2..7554d759a490 100644 --- a/app/src/main/java/com/duckduckgo/app/widget/ui/AddWidgetInstructionsViewModel.kt +++ b/app/src/main/java/com/duckduckgo/app/widget/ui/AddWidgetInstructionsViewModel.kt @@ -18,8 +18,15 @@ package com.duckduckgo.app.widget.ui import androidx.lifecycle.ViewModel import com.duckduckgo.app.global.SingleLiveEvent +import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin import com.duckduckgo.app.widget.ui.AddWidgetInstructionsViewModel.Command.Close import com.duckduckgo.app.widget.ui.AddWidgetInstructionsViewModel.Command.ShowHome +import com.duckduckgo.di.scopes.AppObjectGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet +import javax.inject.Singleton class AddWidgetInstructionsViewModel : ViewModel() { @@ -38,3 +45,25 @@ class AddWidgetInstructionsViewModel : ViewModel() { command.value = Close } } + +@Module +@ContributesTo(AppObjectGraph::class) +class AddWidgetInstructionsViewModelFactoryModule { + @Provides + @Singleton + @IntoSet + fun provideAddWidgetInstructionsViewModelFactory(): ViewModelFactoryPlugin { + return AddWidgetInstructionsViewModelFactory() + } +} + +private class AddWidgetInstructionsViewModelFactory() : ViewModelFactoryPlugin { + override fun create(modelClass: Class): T? { + with(modelClass) { + return when { + isAssignableFrom(AddWidgetInstructionsViewModel::class.java) -> (AddWidgetInstructionsViewModel() as T) + else -> null + } + } + } +} diff --git a/common/src/main/java/com/duckduckgo/app/global/plugins/view_model/ViewModelFactoryPlugin.kt b/common/src/main/java/com/duckduckgo/app/global/plugins/view_model/ViewModelFactoryPlugin.kt new file mode 100644 index 000000000000..8885f5e7a972 --- /dev/null +++ b/common/src/main/java/com/duckduckgo/app/global/plugins/view_model/ViewModelFactoryPlugin.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021 DuckDuckGo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.duckduckgo.app.global.plugins.view_model + +import androidx.lifecycle.ViewModel +import com.duckduckgo.app.global.plugins.PluginPoint +import javax.inject.Inject +import javax.inject.Singleton + +interface ViewModelFactoryPlugin { + fun create(modelClass: Class): T? +} + +@Singleton +class ViewModelFactoryPluginPoint @Inject constructor( + private val injectorPlugins: Set<@JvmSuppressWildcards ViewModelFactoryPlugin> +) : PluginPoint { + override fun getPlugins(): List { + return injectorPlugins.toList() + } +}