Cleanup dagger setup (#2300)
* cleanup dagger setup * fix tests * fix ktlint * cleanup FragmentBuildersModule
This commit is contained in:
parent
0b70f52ad2
commit
e29567c9ec
|
@ -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…
Reference in New Issue