Cleanup dagger setup (#2300)
* cleanup dagger setup * fix tests * fix ktlint * cleanup FragmentBuildersModule
This commit is contained in:
		
					parent
					
						
							
								0b70f52ad2
							
						
					
				
			
			
				commit
				
					
						e29567c9ec
					
				
			
		
					 12 changed files with 44 additions and 159 deletions
				
			
		|  | @ -2,21 +2,19 @@ package com.keylesspalace.tusky.appstore | |||
| 
 | ||||
| import io.reactivex.rxjava3.core.Observable | ||||
| import io.reactivex.rxjava3.subjects.PublishSubject | ||||
| import javax.inject.Inject | ||||
| import javax.inject.Singleton | ||||
| 
 | ||||
| interface Event | ||||
| interface Dispatchable : Event | ||||
| 
 | ||||
| interface EventHub { | ||||
|     val events: Observable<Event> | ||||
|     fun dispatch(event: Dispatchable) | ||||
| } | ||||
| 
 | ||||
| object EventHubImpl : EventHub { | ||||
| @Singleton | ||||
| class EventHub @Inject constructor() { | ||||
| 
 | ||||
|     private val eventsSubject = PublishSubject.create<Event>() | ||||
|     override val events: Observable<Event> = eventsSubject | ||||
|     val events: Observable<Event> = eventsSubject | ||||
| 
 | ||||
|     override fun dispatch(event: Dispatchable) { | ||||
|     fun dispatch(event: Dispatchable) { | ||||
|         eventsSubject.onNext(event) | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -41,6 +41,7 @@ import java.io.File | |||
| import java.io.FileOutputStream | ||||
| import java.io.IOException | ||||
| import java.util.Date | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| sealed class UploadEvent { | ||||
|     data class ProgressEvent(val percentage: Int) : UploadEvent() | ||||
|  | @ -61,21 +62,16 @@ fun createNewImageFile(context: Context): File { | |||
| 
 | ||||
| data class PreparedMedia(val type: QueuedMedia.Type, val uri: Uri, val size: Long) | ||||
| 
 | ||||
| interface MediaUploader { | ||||
|     fun prepareMedia(inUri: Uri): Single<PreparedMedia> | ||||
|     fun uploadMedia(media: QueuedMedia): Observable<UploadEvent> | ||||
| } | ||||
| 
 | ||||
| class AudioSizeException : Exception() | ||||
| class VideoSizeException : Exception() | ||||
| class MediaTypeException : Exception() | ||||
| class CouldNotOpenFileException : Exception() | ||||
| 
 | ||||
| class MediaUploaderImpl( | ||||
| class MediaUploader @Inject constructor( | ||||
|     private val context: Context, | ||||
|     private val mastodonApi: MastodonApi | ||||
| ) : MediaUploader { | ||||
|     override fun uploadMedia(media: QueuedMedia): Observable<UploadEvent> { | ||||
| ) { | ||||
|     fun uploadMedia(media: QueuedMedia): Observable<UploadEvent> { | ||||
|         return Observable | ||||
|             .fromCallable { | ||||
|                 if (shouldResizeMedia(media)) { | ||||
|  | @ -86,7 +82,7 @@ class MediaUploaderImpl( | |||
|             .subscribeOn(Schedulers.io()) | ||||
|     } | ||||
| 
 | ||||
|     override fun prepareMedia(inUri: Uri): Single<PreparedMedia> { | ||||
|     fun prepareMedia(inUri: Uri): Single<PreparedMedia> { | ||||
|         return Single.fromCallable { | ||||
|             var mediaSize = getMediaSize(contentResolver, inUri) | ||||
|             var uri = inUri | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| package com.keylesspalace.tusky.components.notifications | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.util.Log | ||||
| import com.keylesspalace.tusky.db.AccountEntity | ||||
| import com.keylesspalace.tusky.db.AccountManager | ||||
|  | @ -12,7 +13,7 @@ import javax.inject.Inject | |||
| class NotificationFetcher @Inject constructor( | ||||
|     private val mastodonApi: MastodonApi, | ||||
|     private val accountManager: AccountManager, | ||||
|     private val notifier: Notifier | ||||
|     private val context: Context | ||||
| ) { | ||||
|     fun fetchAndShow() { | ||||
|         for (account in accountManager.getAllAccountsOrderedByActive()) { | ||||
|  | @ -20,7 +21,7 @@ class NotificationFetcher @Inject constructor( | |||
|                 try { | ||||
|                     val notifications = fetchNotifications(account) | ||||
|                     notifications.forEachIndexed { index, notification -> | ||||
|                         notifier.show(notification, account, index == 0) | ||||
|                         NotificationHelper.make(context, notification, account, index == 0) | ||||
|                     } | ||||
|                     accountManager.saveAccount(account) | ||||
|                 } catch (e: Exception) { | ||||
|  |  | |||
|  | @ -1,20 +0,0 @@ | |||
| package com.keylesspalace.tusky.components.notifications | ||||
| 
 | ||||
| import android.content.Context | ||||
| import com.keylesspalace.tusky.db.AccountEntity | ||||
| import com.keylesspalace.tusky.entity.Notification | ||||
| 
 | ||||
| /** | ||||
|  * Shows notifications. | ||||
|  */ | ||||
| interface Notifier { | ||||
|     fun show(notification: Notification, account: AccountEntity, isFirstInBatch: Boolean) | ||||
| } | ||||
| 
 | ||||
| class SystemNotifier( | ||||
|     private val context: Context | ||||
| ) : Notifier { | ||||
|     override fun show(notification: Notification, account: AccountEntity, isFirstInBatch: Boolean) { | ||||
|         NotificationHelper.make(context, notification, account, isFirstInBatch) | ||||
|     } | ||||
| } | ||||
|  | @ -34,8 +34,7 @@ import javax.inject.Singleton | |||
|         ActivitiesModule::class, | ||||
|         ServicesModule::class, | ||||
|         BroadcastReceiverModule::class, | ||||
|         ViewModelModule::class, | ||||
|         MediaUploaderModule::class | ||||
|         ViewModelModule::class | ||||
|     ] | ||||
| ) | ||||
| interface AppComponent { | ||||
|  |  | |||
|  | @ -18,19 +18,11 @@ package com.keylesspalace.tusky.di | |||
| import android.app.Application | ||||
| import android.content.Context | ||||
| import android.content.SharedPreferences | ||||
| import androidx.localbroadcastmanager.content.LocalBroadcastManager | ||||
| import androidx.preference.PreferenceManager | ||||
| import androidx.room.Room | ||||
| import com.keylesspalace.tusky.TuskyApplication | ||||
| import com.keylesspalace.tusky.appstore.EventHub | ||||
| import com.keylesspalace.tusky.appstore.EventHubImpl | ||||
| import com.keylesspalace.tusky.components.notifications.Notifier | ||||
| import com.keylesspalace.tusky.components.notifications.SystemNotifier | ||||
| import com.keylesspalace.tusky.db.AppDatabase | ||||
| import com.keylesspalace.tusky.db.Converters | ||||
| import com.keylesspalace.tusky.network.MastodonApi | ||||
| import com.keylesspalace.tusky.network.TimelineCases | ||||
| import com.keylesspalace.tusky.network.TimelineCasesImpl | ||||
| import dagger.Module | ||||
| import dagger.Provides | ||||
| import javax.inject.Singleton | ||||
|  | @ -53,23 +45,6 @@ class AppModule { | |||
|         return PreferenceManager.getDefaultSharedPreferences(app) | ||||
|     } | ||||
| 
 | ||||
|     @Provides | ||||
|     fun providesBroadcastManager(app: Application): LocalBroadcastManager { | ||||
|         return LocalBroadcastManager.getInstance(app) | ||||
|     } | ||||
| 
 | ||||
|     @Provides | ||||
|     fun providesTimelineUseCases( | ||||
|         api: MastodonApi, | ||||
|         eventHub: EventHub | ||||
|     ): TimelineCases { | ||||
|         return TimelineCasesImpl(api, eventHub) | ||||
|     } | ||||
| 
 | ||||
|     @Provides | ||||
|     @Singleton | ||||
|     fun providesEventHub(): EventHub = EventHubImpl | ||||
| 
 | ||||
|     @Provides | ||||
|     @Singleton | ||||
|     fun providesDatabase(appContext: Context, converters: Converters): AppDatabase { | ||||
|  | @ -90,8 +65,4 @@ class AppModule { | |||
|             ) | ||||
|             .build() | ||||
|     } | ||||
| 
 | ||||
|     @Provides | ||||
|     @Singleton | ||||
|     fun notifier(context: Context): Notifier = SystemNotifier(context) | ||||
| } | ||||
|  |  | |||
|  | @ -56,9 +56,6 @@ abstract class FragmentBuildersModule { | |||
|     @ContributesAndroidInjector | ||||
|     abstract fun notificationsFragment(): NotificationsFragment | ||||
| 
 | ||||
|     @ContributesAndroidInjector | ||||
|     abstract fun searchFragment(): SearchStatusesFragment | ||||
| 
 | ||||
|     @ContributesAndroidInjector | ||||
|     abstract fun notificationPreferencesFragment(): NotificationPreferencesFragment | ||||
| 
 | ||||
|  | @ -66,7 +63,7 @@ abstract class FragmentBuildersModule { | |||
|     abstract fun accountPreferencesFragment(): AccountPreferencesFragment | ||||
| 
 | ||||
|     @ContributesAndroidInjector | ||||
|     abstract fun directMessagesPreferencesFragment(): ConversationsFragment | ||||
|     abstract fun conversationsFragment(): ConversationsFragment | ||||
| 
 | ||||
|     @ContributesAndroidInjector | ||||
|     abstract fun accountInListsFragment(): AccountsInListFragment | ||||
|  | @ -83,6 +80,9 @@ abstract class FragmentBuildersModule { | |||
|     @ContributesAndroidInjector | ||||
|     abstract fun instanceListFragment(): InstanceListFragment | ||||
| 
 | ||||
|     @ContributesAndroidInjector | ||||
|     abstract fun searchStatusesFragment(): SearchStatusesFragment | ||||
| 
 | ||||
|     @ContributesAndroidInjector | ||||
|     abstract fun searchAccountFragment(): SearchAccountsFragment | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,30 +0,0 @@ | |||
| /* Copyright 2019 Tusky Contributors | ||||
|  * | ||||
|  * This file is a part of Tusky. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it under the terms of the | ||||
|  * GNU General Public License as published by the Free Software Foundation; either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even | ||||
|  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General | ||||
|  * Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with Tusky; if not, | ||||
|  * see <http://www.gnu.org/licenses>. */ | ||||
| 
 | ||||
| package com.keylesspalace.tusky.di | ||||
| 
 | ||||
| import android.content.Context | ||||
| import com.keylesspalace.tusky.components.compose.MediaUploader | ||||
| import com.keylesspalace.tusky.components.compose.MediaUploaderImpl | ||||
| import com.keylesspalace.tusky.network.MastodonApi | ||||
| import dagger.Module | ||||
| import dagger.Provides | ||||
| 
 | ||||
| @Module | ||||
| class MediaUploaderModule { | ||||
|     @Provides | ||||
|     fun providesMediaUploder(context: Context, mastodonApi: MastodonApi): MediaUploader = | ||||
|         MediaUploaderImpl(context, mastodonApi) | ||||
| } | ||||
|  | @ -15,25 +15,12 @@ | |||
| 
 | ||||
| package com.keylesspalace.tusky.di | ||||
| 
 | ||||
| import android.content.Context | ||||
| import com.keylesspalace.tusky.service.SendTootService | ||||
| import com.keylesspalace.tusky.service.ServiceClient | ||||
| import com.keylesspalace.tusky.service.ServiceClientImpl | ||||
| import dagger.Module | ||||
| import dagger.Provides | ||||
| import dagger.android.ContributesAndroidInjector | ||||
| 
 | ||||
| @Module | ||||
| abstract class ServicesModule { | ||||
|     @ContributesAndroidInjector | ||||
|     abstract fun contributesSendTootService(): SendTootService | ||||
| 
 | ||||
|     @Module | ||||
|     companion object { | ||||
|         @Provides | ||||
|         @JvmStatic | ||||
|         fun providesServiceClient(context: Context): ServiceClient { | ||||
|             return ServiceClientImpl(context) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -32,27 +32,16 @@ import com.keylesspalace.tusky.entity.Status | |||
| import io.reactivex.rxjava3.core.Single | ||||
| import io.reactivex.rxjava3.disposables.CompositeDisposable | ||||
| import io.reactivex.rxjava3.kotlin.addTo | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| /** | ||||
|  * Created by charlag on 3/24/18. | ||||
|  */ | ||||
| 
 | ||||
| interface TimelineCases { | ||||
|     fun reblog(statusId: String, reblog: Boolean): Single<Status> | ||||
|     fun favourite(statusId: String, favourite: Boolean): Single<Status> | ||||
|     fun bookmark(statusId: String, bookmark: Boolean): Single<Status> | ||||
|     fun mute(statusId: String, notifications: Boolean, duration: Int?) | ||||
|     fun block(statusId: String) | ||||
|     fun delete(statusId: String): Single<DeletedStatus> | ||||
|     fun pin(statusId: String, pin: Boolean): Single<Status> | ||||
|     fun voteInPoll(statusId: String, pollId: String, choices: List<Int>): Single<Poll> | ||||
|     fun muteConversation(statusId: String, mute: Boolean): Single<Status> | ||||
| } | ||||
| 
 | ||||
| class TimelineCasesImpl( | ||||
| class TimelineCases @Inject constructor( | ||||
|     private val mastodonApi: MastodonApi, | ||||
|     private val eventHub: EventHub | ||||
| ) : TimelineCases { | ||||
| ) { | ||||
| 
 | ||||
|     /** | ||||
|      * Unused yet but can be use for cancellation later. It's always a good idea to save | ||||
|  | @ -60,7 +49,7 @@ class TimelineCasesImpl( | |||
|      */ | ||||
|     private val cancelDisposable = CompositeDisposable() | ||||
| 
 | ||||
|     override fun reblog(statusId: String, reblog: Boolean): Single<Status> { | ||||
|     fun reblog(statusId: String, reblog: Boolean): Single<Status> { | ||||
|         val call = if (reblog) { | ||||
|             mastodonApi.reblogStatus(statusId) | ||||
|         } else { | ||||
|  | @ -71,7 +60,7 @@ class TimelineCasesImpl( | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun favourite(statusId: String, favourite: Boolean): Single<Status> { | ||||
|     fun favourite(statusId: String, favourite: Boolean): Single<Status> { | ||||
|         val call = if (favourite) { | ||||
|             mastodonApi.favouriteStatus(statusId) | ||||
|         } else { | ||||
|  | @ -82,7 +71,7 @@ class TimelineCasesImpl( | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun bookmark(statusId: String, bookmark: Boolean): Single<Status> { | ||||
|     fun bookmark(statusId: String, bookmark: Boolean): Single<Status> { | ||||
|         val call = if (bookmark) { | ||||
|             mastodonApi.bookmarkStatus(statusId) | ||||
|         } else { | ||||
|  | @ -93,7 +82,7 @@ class TimelineCasesImpl( | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun muteConversation(statusId: String, mute: Boolean): Single<Status> { | ||||
|     fun muteConversation(statusId: String, mute: Boolean): Single<Status> { | ||||
|         val call = if (mute) { | ||||
|             mastodonApi.muteConversation(statusId) | ||||
|         } else { | ||||
|  | @ -104,7 +93,7 @@ class TimelineCasesImpl( | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     override fun mute(statusId: String, notifications: Boolean, duration: Int?) { | ||||
|     fun mute(statusId: String, notifications: Boolean, duration: Int?) { | ||||
|         mastodonApi.muteAccount(statusId, notifications, duration) | ||||
|             .subscribe( | ||||
|                 { | ||||
|  | @ -117,7 +106,7 @@ class TimelineCasesImpl( | |||
|             .addTo(cancelDisposable) | ||||
|     } | ||||
| 
 | ||||
|     override fun block(statusId: String) { | ||||
|     fun block(statusId: String) { | ||||
|         mastodonApi.blockAccount(statusId) | ||||
|             .subscribe( | ||||
|                 { | ||||
|  | @ -130,14 +119,14 @@ class TimelineCasesImpl( | |||
|             .addTo(cancelDisposable) | ||||
|     } | ||||
| 
 | ||||
|     override fun delete(statusId: String): Single<DeletedStatus> { | ||||
|     fun delete(statusId: String): Single<DeletedStatus> { | ||||
|         return mastodonApi.deleteStatus(statusId) | ||||
|             .doAfterSuccess { | ||||
|                 eventHub.dispatch(StatusDeletedEvent(statusId)) | ||||
|             } | ||||
|     } | ||||
| 
 | ||||
|     override fun pin(statusId: String, pin: Boolean): Single<Status> { | ||||
|     fun pin(statusId: String, pin: Boolean): Single<Status> { | ||||
|         // Replace with extension method if we use RxKotlin | ||||
|         return (if (pin) mastodonApi.pinStatus(statusId) else mastodonApi.unpinStatus(statusId)) | ||||
|             .doAfterSuccess { | ||||
|  | @ -145,7 +134,7 @@ class TimelineCasesImpl( | |||
|             } | ||||
|     } | ||||
| 
 | ||||
|     override fun voteInPoll(statusId: String, pollId: String, choices: List<Int>): Single<Poll> { | ||||
|     fun voteInPoll(statusId: String, pollId: String, choices: List<Int>): Single<Poll> { | ||||
|         if (choices.isEmpty()) { | ||||
|             return Single.error(IllegalStateException()) | ||||
|         } | ||||
|  |  | |||
|  | @ -16,19 +16,12 @@ | |||
| package com.keylesspalace.tusky.service | ||||
| 
 | ||||
| import android.content.Context | ||||
| import android.os.Build | ||||
| import androidx.core.content.ContextCompat | ||||
| import javax.inject.Inject | ||||
| 
 | ||||
| interface ServiceClient { | ||||
|     fun sendToot(tootToSend: TootToSend) | ||||
| } | ||||
| 
 | ||||
| class ServiceClientImpl(private val context: Context) : ServiceClient { | ||||
|     override fun sendToot(tootToSend: TootToSend) { | ||||
| class ServiceClient @Inject constructor(private val context: Context) { | ||||
|     fun sendToot(tootToSend: TootToSend) { | ||||
|         val intent = SendTootService.sendTootIntent(context, tootToSend) | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { | ||||
|             context.startForegroundService(intent) | ||||
|         } else { | ||||
|             context.startService(intent) | ||||
|         } | ||||
|         ContextCompat.startForegroundService(context, intent) | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ import androidx.room.Room | |||
| import androidx.test.ext.junit.runners.AndroidJUnit4 | ||||
| import androidx.test.platform.app.InstrumentationRegistry | ||||
| import com.google.gson.Gson | ||||
| import com.keylesspalace.tusky.appstore.EventHubImpl | ||||
| import com.keylesspalace.tusky.appstore.EventHub | ||||
| import com.keylesspalace.tusky.components.timeline.TimelinePagingAdapter.Companion.TimelineDifferCallback | ||||
| import com.keylesspalace.tusky.components.timeline.viewmodel.CachedTimelineViewModel | ||||
| import com.keylesspalace.tusky.components.timeline.viewmodel.NetworkTimelineViewModel | ||||
|  | @ -20,7 +20,7 @@ import com.keylesspalace.tusky.db.AppDatabase | |||
| import com.keylesspalace.tusky.db.Converters | ||||
| import com.keylesspalace.tusky.network.FilterModel | ||||
| import com.keylesspalace.tusky.network.MastodonApi | ||||
| import com.keylesspalace.tusky.network.TimelineCasesImpl | ||||
| import com.keylesspalace.tusky.network.TimelineCases | ||||
| import com.nhaarman.mockitokotlin2.doReturn | ||||
| import com.nhaarman.mockitokotlin2.mock | ||||
| import io.reactivex.rxjava3.core.Single | ||||
|  | @ -66,6 +66,8 @@ class TimelineViewModelTest { | |||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     private val eventHub = EventHub() | ||||
| 
 | ||||
|     private lateinit var db: AppDatabase | ||||
| 
 | ||||
|     @Before | ||||
|  | @ -115,9 +117,9 @@ class TimelineViewModelTest { | |||
|         } | ||||
| 
 | ||||
|         val viewModel = NetworkTimelineViewModel( | ||||
|             TimelineCasesImpl(api, EventHubImpl), | ||||
|             TimelineCases(api, eventHub), | ||||
|             api, | ||||
|             EventHubImpl, | ||||
|             eventHub, | ||||
|             accountManager, | ||||
|             mock(), | ||||
|             FilterModel() | ||||
|  | @ -171,9 +173,9 @@ class TimelineViewModelTest { | |||
|         } | ||||
| 
 | ||||
|         val viewModel = CachedTimelineViewModel( | ||||
|             TimelineCasesImpl(api, EventHubImpl), | ||||
|             TimelineCases(api, eventHub), | ||||
|             api, | ||||
|             EventHubImpl, | ||||
|             eventHub, | ||||
|             accountManager, | ||||
|             mock(), | ||||
|             FilterModel(), | ||||
|  | @ -189,7 +191,6 @@ class TimelineViewModelTest { | |||
|             workerDispatcher = testDispatcher | ||||
|         ) | ||||
| 
 | ||||
|         var x = 1 | ||||
|         viewModel.statuses.take(1000).collectLatest { | ||||
|             testScope.launch { | ||||
|                 differ.submitData(it) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue