Skip to content

Commit c3b4098

Browse files
authored
Refactor the ViewModelFactory to use multibindings (#1123)
* Refactor the ViewModelFactory to use multibindings * Moved dagger module and VM factory to the botton of the files
1 parent 79e6c57 commit c3b4098

28 files changed

+1039
-236
lines changed

app/src/main/java/com/duckduckgo/app/bookmarks/ui/BookmarksViewModel.kt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,16 @@ import com.duckduckgo.app.bookmarks.ui.EditBookmarkDialogFragment.EditBookmarkLi
2828
import com.duckduckgo.app.browser.favicon.FaviconManager
2929
import com.duckduckgo.app.global.DispatcherProvider
3030
import com.duckduckgo.app.global.SingleLiveEvent
31+
import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin
32+
import com.duckduckgo.di.scopes.AppObjectGraph
33+
import com.squareup.anvil.annotations.ContributesTo
34+
import dagger.Module
35+
import dagger.Provides
36+
import dagger.multibindings.IntoSet
3137
import io.reactivex.schedulers.Schedulers
3238
import kotlinx.coroutines.NonCancellable
3339
import kotlinx.coroutines.launch
40+
import javax.inject.Singleton
3441

3542
class BookmarksViewModel(
3643
val dao: BookmarksDao,
@@ -112,3 +119,33 @@ class BookmarksViewModel(
112119
}
113120

114121
}
122+
123+
@Module
124+
@ContributesTo(AppObjectGraph::class)
125+
class BookmarksViewModelFactoryModule {
126+
@Provides
127+
@Singleton
128+
@IntoSet
129+
fun provideBookmarksViewModelFactory(
130+
dao: BookmarksDao,
131+
faviconManager: FaviconManager,
132+
dispatcherProvider: DispatcherProvider
133+
): ViewModelFactoryPlugin {
134+
return BookmarksViewModelFactory(dao, faviconManager, dispatcherProvider)
135+
}
136+
}
137+
138+
private class BookmarksViewModelFactory(
139+
private val dao: BookmarksDao,
140+
private val faviconManager: FaviconManager,
141+
private val dispatcherProvider: DispatcherProvider
142+
) : ViewModelFactoryPlugin {
143+
override fun <T : ViewModel?> create(modelClass: Class<T>): T? {
144+
with(modelClass) {
145+
return when {
146+
isAssignableFrom(BookmarksViewModel::class.java) -> (BookmarksViewModel(dao, faviconManager, dispatcherProvider) as T)
147+
else -> null
148+
}
149+
}
150+
}
151+
}

app/src/main/java/com/duckduckgo/app/brokensite/BrokenSiteViewModel.kt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,14 @@ import com.duckduckgo.app.brokensite.model.BrokenSiteCategory.*
2727
import com.duckduckgo.app.global.SingleLiveEvent
2828
import com.duckduckgo.app.global.absoluteString
2929
import com.duckduckgo.app.global.isMobileSite
30+
import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin
3031
import com.duckduckgo.app.statistics.pixels.Pixel
32+
import com.duckduckgo.di.scopes.AppObjectGraph
33+
import com.squareup.anvil.annotations.ContributesTo
34+
import dagger.Module
35+
import dagger.Provides
36+
import dagger.multibindings.IntoSet
37+
import javax.inject.Singleton
3138

3239
class BrokenSiteViewModel(private val pixel: Pixel, private val brokenSiteSender: BrokenSiteSender) : ViewModel() {
3340

@@ -118,3 +125,31 @@ class BrokenSiteViewModel(private val pixel: Pixel, private val brokenSiteSender
118125
const val DESKTOP_SITE = "desktop"
119126
}
120127
}
128+
129+
@Module
130+
@ContributesTo(AppObjectGraph::class)
131+
class BrokenSiteViewModelFactoryModule {
132+
@Provides
133+
@Singleton
134+
@IntoSet
135+
fun provideBrokenSiteViewModelFactory(
136+
pixel: Pixel,
137+
brokenSiteSender: BrokenSiteSender
138+
): ViewModelFactoryPlugin {
139+
return BrokenSiteViewModelFactory(pixel, brokenSiteSender)
140+
}
141+
}
142+
143+
private class BrokenSiteViewModelFactory(
144+
private val pixel: Pixel,
145+
private val brokenSiteSender: BrokenSiteSender
146+
) : ViewModelFactoryPlugin {
147+
override fun <T : ViewModel?> create(modelClass: Class<T>): T? {
148+
with(modelClass) {
149+
return when {
150+
isAssignableFrom(BrokenSiteViewModel::class.java) -> (BrokenSiteViewModel(pixel, brokenSiteSender) as T)
151+
else -> null
152+
}
153+
}
154+
}
155+
}

app/src/main/java/com/duckduckgo/app/browser/BrowserTabViewModel.kt

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteResult
3838
import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion
3939
import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion.AutoCompleteBookmarkSuggestion
4040
import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion.AutoCompleteSearchSuggestion
41+
import com.duckduckgo.app.autocomplete.api.AutoCompleteApi
4142
import com.duckduckgo.app.bookmarks.db.BookmarkEntity
4243
import com.duckduckgo.app.bookmarks.db.BookmarksDao
4344
import com.duckduckgo.app.bookmarks.ui.EditBookmarkDialogFragment.EditBookmarkListener
@@ -61,6 +62,7 @@ import com.duckduckgo.app.browser.model.BasicAuthenticationCredentials
6162
import com.duckduckgo.app.browser.model.BasicAuthenticationRequest
6263
import com.duckduckgo.app.browser.model.LongPressTarget
6364
import com.duckduckgo.app.browser.omnibar.OmnibarEntryConverter
65+
import com.duckduckgo.app.browser.omnibar.QueryUrlConverter
6466
import com.duckduckgo.app.browser.session.WebViewSessionStorage
6567
import com.duckduckgo.app.browser.ui.HttpAuthenticationDialogFragment.HttpAuthenticationListener
6668
import com.duckduckgo.app.cta.ui.*
@@ -73,6 +75,7 @@ import com.duckduckgo.app.global.model.Site
7375
import com.duckduckgo.app.global.model.SiteFactory
7476
import com.duckduckgo.app.global.model.domain
7577
import com.duckduckgo.app.global.model.domainMatchesUrl
78+
import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin
7679
import com.duckduckgo.app.global.useourapp.UseOurAppDetector
7780
import com.duckduckgo.app.global.useourapp.UseOurAppDetector.Companion.USE_OUR_APP_SHORTCUT_TITLE
7881
import com.duckduckgo.app.global.useourapp.UseOurAppDetector.Companion.USE_OUR_APP_SHORTCUT_URL
@@ -100,7 +103,12 @@ import com.duckduckgo.app.tabs.model.TabEntity
100103
import com.duckduckgo.app.tabs.model.TabRepository
101104
import com.duckduckgo.app.trackerdetection.model.TrackingEvent
102105
import com.duckduckgo.app.usage.search.SearchCountDao
106+
import com.duckduckgo.di.scopes.AppObjectGraph
103107
import com.jakewharton.rxrelay2.PublishRelay
108+
import com.squareup.anvil.annotations.ContributesTo
109+
import dagger.Module
110+
import dagger.Provides
111+
import dagger.multibindings.IntoSet
104112
import io.reactivex.android.schedulers.AndroidSchedulers
105113
import io.reactivex.disposables.Disposable
106114
import io.reactivex.schedulers.Schedulers
@@ -109,6 +117,7 @@ import timber.log.Timber
109117
import java.io.File
110118
import java.util.*
111119
import java.util.concurrent.TimeUnit
120+
import javax.inject.Singleton
112121

113122
class BrowserTabViewModel(
114123
private val statisticsUpdater: StatisticsUpdater,
@@ -1832,3 +1841,118 @@ class BrowserTabViewModel(
18321841
private const val ONE_HOUR_IN_MS = 3_600_000
18331842
}
18341843
}
1844+
1845+
@Module
1846+
@ContributesTo(AppObjectGraph::class)
1847+
class BrowserTabViewModelFactoryModule {
1848+
@Provides
1849+
@Singleton
1850+
@IntoSet
1851+
fun provideBrowserTabViewModelFactory(
1852+
statisticsUpdater: StatisticsUpdater,
1853+
queryUrlConverter: QueryUrlConverter,
1854+
duckDuckGoUrlDetector: DuckDuckGoUrlDetector,
1855+
siteFactory: SiteFactory,
1856+
tabRepository: TabRepository,
1857+
userWhitelistDao: UserWhitelistDao,
1858+
networkLeaderboardDao: NetworkLeaderboardDao,
1859+
bookmarksDao: BookmarksDao,
1860+
fireproofWebsiteRepository: FireproofWebsiteRepository,
1861+
locationPermissionsRepository: LocationPermissionsRepository,
1862+
geoLocationPermissions: GeoLocationPermissions,
1863+
navigationAwareLoginDetector: NavigationAwareLoginDetector,
1864+
autoCompleteApi: AutoCompleteApi,
1865+
appSettingsPreferencesStore: SettingsDataStore,
1866+
longPressHandler: LongPressHandler,
1867+
webViewSessionStorage: WebViewSessionStorage,
1868+
specialUrlDetector: SpecialUrlDetector,
1869+
faviconManager: FaviconManager,
1870+
addToHomeCapabilityDetector: AddToHomeCapabilityDetector,
1871+
ctaViewModel: CtaViewModel,
1872+
searchCountDao: SearchCountDao,
1873+
pixel: Pixel,
1874+
dispatchers: DispatcherProvider = DefaultDispatcherProvider(),
1875+
userEventsStore: UserEventsStore,
1876+
notificationDao: NotificationDao,
1877+
useOurAppDetector: UseOurAppDetector,
1878+
variantManager: VariantManager,
1879+
fileDownloader: FileDownloader,
1880+
globalPrivacyControl: GlobalPrivacyControl,
1881+
fireproofDialogsEventHandler: FireproofDialogsEventHandler
1882+
): ViewModelFactoryPlugin {
1883+
return BrowserTabViewModelFactory(
1884+
statisticsUpdater,
1885+
queryUrlConverter,
1886+
duckDuckGoUrlDetector,
1887+
siteFactory,
1888+
tabRepository,
1889+
userWhitelistDao,
1890+
networkLeaderboardDao,
1891+
bookmarksDao,
1892+
fireproofWebsiteRepository,
1893+
locationPermissionsRepository,
1894+
geoLocationPermissions,
1895+
navigationAwareLoginDetector,
1896+
autoCompleteApi,
1897+
appSettingsPreferencesStore,
1898+
longPressHandler,
1899+
webViewSessionStorage,
1900+
specialUrlDetector,
1901+
faviconManager,
1902+
addToHomeCapabilityDetector,
1903+
ctaViewModel,
1904+
searchCountDao,
1905+
pixel,
1906+
dispatchers,
1907+
userEventsStore,
1908+
notificationDao,
1909+
useOurAppDetector,
1910+
variantManager,
1911+
fileDownloader,
1912+
globalPrivacyControl,
1913+
fireproofDialogsEventHandler
1914+
)
1915+
}
1916+
}
1917+
1918+
private class BrowserTabViewModelFactory(
1919+
private val statisticsUpdater: StatisticsUpdater,
1920+
private val queryUrlConverter: OmnibarEntryConverter,
1921+
private val duckDuckGoUrlDetector: DuckDuckGoUrlDetector,
1922+
private val siteFactory: SiteFactory,
1923+
private val tabRepository: TabRepository,
1924+
private val userWhitelistDao: UserWhitelistDao,
1925+
private val networkLeaderboardDao: NetworkLeaderboardDao,
1926+
private val bookmarksDao: BookmarksDao,
1927+
private val fireproofWebsiteRepository: FireproofWebsiteRepository,
1928+
private val locationPermissionsRepository: LocationPermissionsRepository,
1929+
private val geoLocationPermissions: GeoLocationPermissions,
1930+
private val navigationAwareLoginDetector: NavigationAwareLoginDetector,
1931+
private val autoComplete: AutoComplete,
1932+
private val appSettingsPreferencesStore: SettingsDataStore,
1933+
private val longPressHandler: LongPressHandler,
1934+
private val webViewSessionStorage: WebViewSessionStorage,
1935+
private val specialUrlDetector: SpecialUrlDetector,
1936+
private val faviconManager: FaviconManager,
1937+
private val addToHomeCapabilityDetector: AddToHomeCapabilityDetector,
1938+
private val ctaViewModel: CtaViewModel,
1939+
private val searchCountDao: SearchCountDao,
1940+
private val pixel: Pixel,
1941+
private val dispatchers: DispatcherProvider = DefaultDispatcherProvider(),
1942+
private val userEventsStore: UserEventsStore,
1943+
private val notificationDao: NotificationDao,
1944+
private val useOurAppDetector: UseOurAppDetector,
1945+
private val variantManager: VariantManager,
1946+
private val fileDownloader: FileDownloader,
1947+
private val globalPrivacyControl: GlobalPrivacyControl,
1948+
private val fireproofDialogsEventHandler: FireproofDialogsEventHandler
1949+
) : ViewModelFactoryPlugin {
1950+
override fun <T : ViewModel?> create(modelClass: Class<T>): T? {
1951+
with(modelClass) {
1952+
return when {
1953+
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
1954+
else -> null
1955+
}
1956+
}
1957+
}
1958+
}

app/src/main/java/com/duckduckgo/app/browser/BrowserViewModel.kt

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import androidx.lifecycle.ViewModel
2424
import com.duckduckgo.app.browser.BrowserViewModel.Command.DisplayMessage
2525
import com.duckduckgo.app.browser.BrowserViewModel.Command.Refresh
2626
import com.duckduckgo.app.browser.omnibar.OmnibarEntryConverter
27+
import com.duckduckgo.app.browser.omnibar.QueryUrlConverter
2728
import com.duckduckgo.app.browser.rating.ui.AppEnjoymentDialogFragment
2829
import com.duckduckgo.app.browser.rating.ui.GiveFeedbackDialogFragment
2930
import com.duckduckgo.app.browser.rating.ui.RateAppDialogFragment
@@ -32,6 +33,7 @@ import com.duckduckgo.app.global.ApplicationClearDataState
3233
import com.duckduckgo.app.global.DefaultDispatcherProvider
3334
import com.duckduckgo.app.global.DispatcherProvider
3435
import com.duckduckgo.app.global.SingleLiveEvent
36+
import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin
3537
import com.duckduckgo.app.global.rating.AppEnjoymentPromptEmitter
3638
import com.duckduckgo.app.global.rating.AppEnjoymentPromptOptions
3739
import com.duckduckgo.app.global.rating.AppEnjoymentUserEventRecorder
@@ -41,10 +43,16 @@ import com.duckduckgo.app.privacy.ui.PrivacyDashboardActivity.Companion.RELOAD_R
4143
import com.duckduckgo.app.statistics.pixels.Pixel
4244
import com.duckduckgo.app.tabs.model.TabEntity
4345
import com.duckduckgo.app.tabs.model.TabRepository
46+
import com.duckduckgo.di.scopes.AppObjectGraph
47+
import com.squareup.anvil.annotations.ContributesTo
48+
import dagger.Module
49+
import dagger.Provides
50+
import dagger.multibindings.IntoSet
4451
import kotlinx.coroutines.CoroutineScope
4552
import kotlinx.coroutines.Dispatchers
4653
import kotlinx.coroutines.launch
4754
import timber.log.Timber
55+
import javax.inject.Singleton
4856
import kotlin.coroutines.CoroutineContext
4957

5058
class BrowserViewModel(
@@ -231,3 +239,43 @@ class BrowserViewModel(
231239
}
232240
}
233241
}
242+
243+
@Module
244+
@ContributesTo(AppObjectGraph::class)
245+
class BrowserViewModelFactoryModule {
246+
@Provides
247+
@Singleton
248+
@IntoSet
249+
fun provideBrowserViewModelFactory(
250+
tabRepository: TabRepository,
251+
queryUrlConverter: QueryUrlConverter,
252+
dataClearer: DataClearer,
253+
appEnjoymentPromptEmitter: AppEnjoymentPromptEmitter,
254+
appEnjoymentUserEventRecorder: AppEnjoymentUserEventRecorder,
255+
dispatchers: DispatcherProvider = DefaultDispatcherProvider(),
256+
pixel: Pixel,
257+
useOurAppDetector: UseOurAppDetector
258+
): ViewModelFactoryPlugin {
259+
return BrowserViewModelFactory(tabRepository, queryUrlConverter, dataClearer, appEnjoymentPromptEmitter, appEnjoymentUserEventRecorder, dispatchers, pixel, useOurAppDetector)
260+
}
261+
}
262+
263+
private class BrowserViewModelFactory(
264+
val tabRepository: TabRepository,
265+
val queryUrlConverter: OmnibarEntryConverter,
266+
val dataClearer: DataClearer,
267+
val appEnjoymentPromptEmitter: AppEnjoymentPromptEmitter,
268+
val appEnjoymentUserEventRecorder: AppEnjoymentUserEventRecorder,
269+
val dispatchers: DispatcherProvider = DefaultDispatcherProvider(),
270+
val pixel: Pixel,
271+
val useOurAppDetector: UseOurAppDetector
272+
) : ViewModelFactoryPlugin {
273+
override fun <T : ViewModel?> create(modelClass: Class<T>): T? {
274+
with(modelClass) {
275+
return when {
276+
isAssignableFrom(BrowserViewModel::class.java) -> BrowserViewModel(tabRepository, queryUrlConverter, dataClearer, appEnjoymentPromptEmitter, appEnjoymentUserEventRecorder, dispatchers, pixel, useOurAppDetector) as T
277+
else -> null
278+
}
279+
}
280+
}
281+
}

app/src/main/java/com/duckduckgo/app/feedback/ui/common/FeedbackViewModel.kt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,19 @@ import com.duckduckgo.app.feedback.ui.negative.FeedbackType
2525
import com.duckduckgo.app.feedback.ui.negative.FeedbackType.MainReason
2626
import com.duckduckgo.app.feedback.ui.negative.FeedbackType.SubReason
2727
import com.duckduckgo.app.global.SingleLiveEvent
28+
import com.duckduckgo.app.global.plugins.view_model.ViewModelFactoryPlugin
2829
import com.duckduckgo.app.playstore.PlayStoreUtils
30+
import com.duckduckgo.di.scopes.AppObjectGraph
31+
import com.squareup.anvil.annotations.ContributesTo
32+
import dagger.Module
33+
import dagger.Provides
34+
import dagger.multibindings.IntoSet
2935
import kotlinx.coroutines.Dispatchers
3036
import kotlinx.coroutines.GlobalScope
3137
import kotlinx.coroutines.launch
3238
import kotlinx.coroutines.withContext
3339
import timber.log.Timber
40+
import javax.inject.Singleton
3441

3542
class FeedbackViewModel(private val playStoreUtils: PlayStoreUtils, private val feedbackSubmitter: FeedbackSubmitter) : ViewModel() {
3643

@@ -282,3 +289,31 @@ data class UpdateViewCommand(
282289
val mainReason: MainReason? = null,
283290
val subReason: SubReason? = null
284291
)
292+
293+
@Module
294+
@ContributesTo(AppObjectGraph::class)
295+
class FeedbackViewModelFactoryModule {
296+
@Provides
297+
@Singleton
298+
@IntoSet
299+
fun provideFeedbackViewModelFactory(
300+
playStoreUtils: PlayStoreUtils,
301+
feedbackSubmitter: FeedbackSubmitter
302+
): ViewModelFactoryPlugin {
303+
return FeedbackViewModelFactory(playStoreUtils, feedbackSubmitter)
304+
}
305+
}
306+
307+
private class FeedbackViewModelFactory(
308+
private val playStoreUtils: PlayStoreUtils,
309+
private val feedbackSubmitter: FeedbackSubmitter
310+
) : ViewModelFactoryPlugin {
311+
override fun <T : ViewModel?> create(modelClass: Class<T>): T? {
312+
with(modelClass) {
313+
return when {
314+
isAssignableFrom(FeedbackViewModel::class.java) -> (FeedbackViewModel(playStoreUtils, feedbackSubmitter) as T)
315+
else -> null
316+
}
317+
}
318+
}
319+
}

0 commit comments

Comments
 (0)