Replace Dagger-Android with Hilt and remove Kapt (#4423)

Hilt is an annotation processor built on top of Dagger which allows to
remove all the Android dependency injection boilerplate code (currently
around 900 lines) by writing it for us.

Hilt can use KSP instead of Kapt so Kapt can be completely removed from
the project. Kapt is slow, deprecated and has a few compatibility
issues. Removing Kapt will improve build times since no Java stubs have
to be generated for Kotlin classes anymore (Note that KSP also processes
annotations in Java classes so it can completely replace Kapt).

- Remove all modules related to manual dependency injection
configuration.
- Rename `AppModule` to `StorageModule` since it now only contains
configuration to retrieve the DataBase and SharedPreferences.
- Annotate all entry points (Activities, Fragments, BroadcastReceivers
and Services) with `@AndroidEntryPoint`.
- Annotate all injected ViewModels with `@HiltViewModel` and replace the
custom ViewModel Factory with the default one (which integrates with the
one generated by Hilt).
- Add a public field to allow overriding the default
ViewModelProvider.Factory in `BaseActivity` in tests.
- Annotate tested Activities with `@OptionalInject` since Activity tests
currently rely on the Activities not being injected automatically.
- Annotate injected `Context` arguments with `@ApplicationContext`. Hilt
provides the `Context` binding automatically but requires to specify if
the Application or Activity Context is wanted.
- Add WorkManager Hilt integration so all Workers are injected by Hilt
automatically using `HiltWorkerFactory`.
- Lazily initialize WorkManager in `TuskyApplication`.
- Remove Kapt and Kapt workarounds.
- ~~Remove toolchain configuration for Java 21. Toolchains force the
Java bytecode to match the JDK version used to build the project, and
apparently Hilt doesn't run inside the toolchain so cannot process the
source code if the JDK version of the toolchain is higher than the JDK
used to run Gradle. [And configuring a toolchain for an older Java
version causes other
issues](https://jakewharton.com/gradle-toolchains-are-rarely-a-good-idea/).
**Removing toolchains configuration doesn't prevent the project from
being built using JDK 21** or more recent versions but allows to build
the project using older JDKs as well.~~
Added a fix to allow Hilt to properly use the JDK toolchain.
- ~~Set the Java and Kotlin bytecode target to Java 17. The standard
bytecode target for Android projects is usually Java 8 or 11 (any higher
version doesn't provide any benefit but may cause compatibility issues).
However, since the app currently uses a library built against Java 17
bytecode (`networkresult-calladapter`), it needs to target at least Java
17 bytecode as well.~~
- Update the Dagger 2 URL in the licenses screen. Hilt is part of Dagger
2 so the label wasn't changed.
This commit is contained in:
Christophe Beyls 2024-05-10 15:55:07 +02:00 committed by GitHub
parent c1fe58c48c
commit dc4ca06551
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
111 changed files with 344 additions and 1253 deletions

View file

@ -1,8 +1,8 @@
plugins { plugins {
alias(libs.plugins.android.application) alias(libs.plugins.android.application)
alias(libs.plugins.google.ksp) alias(libs.plugins.google.ksp)
alias(libs.plugins.hilt.android)
alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.kapt)
alias(libs.plugins.kotlin.parcelize) alias(libs.plugins.kotlin.parcelize)
} }
@ -81,6 +81,7 @@ android {
resValues true resValues true
viewBinding true viewBinding true
} }
testOptions { testOptions {
unitTests { unitTests {
returnDefaultValues = true returnDefaultValues = true
@ -156,8 +157,10 @@ dependencies {
implementation libs.bundles.glide implementation libs.bundles.glide
ksp libs.glide.compiler ksp libs.glide.compiler
implementation libs.bundles.dagger implementation libs.hilt.android
kapt libs.bundles.dagger.processors ksp libs.hilt.compiler
implementation libs.androidx.hilt.work
ksp libs.androidx.hilt.compiler
implementation libs.sparkbutton implementation libs.sparkbutton
@ -189,20 +192,3 @@ dependencies {
androidTestImplementation libs.androidx.room.testing androidTestImplementation libs.androidx.room.testing
androidTestImplementation libs.androidx.test.junit androidTestImplementation libs.androidx.test.junit
} }
// Work around warnings of:
// WARNING: Illegal reflective access by org.jetbrains.kotlin.kapt3.util.ModuleManipulationUtilsKt (file:/C:/Users/Andi/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-annotation-processing-gradle/1.8.22/28dab7e0ee9ce62c03bf97de3543c911dc653700/kotlin-annotation-processing-gradle-1.8.22.jar) to constructor com.sun.tools.javac.util.Context()
// See https://youtrack.jetbrains.com/issue/KT-30589/Kapt-An-illegal-reflective-access-operation-has-occurred
tasks.withType(org.jetbrains.kotlin.gradle.internal.KaptWithoutKotlincTask).configureEach {
kaptProcessJvmArgs.addAll([
"--add-opens", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
"--add-opens", "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
"--add-opens", "jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED",
"--add-opens", "jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED",
"--add-opens", "jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED",
"--add-opens", "jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED",
"--add-opens", "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
"--add-opens", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
"--add-opens", "jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED",
"--add-opens", "jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"])
}

View file

@ -17,15 +17,16 @@ import androidx.annotation.StringRes
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.keylesspalace.tusky.components.instanceinfo.InstanceInfoRepository import com.keylesspalace.tusky.components.instanceinfo.InstanceInfoRepository
import com.keylesspalace.tusky.databinding.ActivityAboutBinding import com.keylesspalace.tusky.databinding.ActivityAboutBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.util.NoUnderlineURLSpan import com.keylesspalace.tusky.util.NoUnderlineURLSpan
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class AboutActivity : BottomSheetActivity(), Injectable { @AndroidEntryPoint
class AboutActivity : BottomSheetActivity() {
@Inject @Inject
lateinit var instanceInfoRepository: InstanceInfoRepository lateinit var instanceInfoRepository: InstanceInfoRepository

View file

@ -31,8 +31,6 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.ListAdapter
import com.keylesspalace.tusky.databinding.FragmentAccountsInListBinding import com.keylesspalace.tusky.databinding.FragmentAccountsInListBinding
import com.keylesspalace.tusky.databinding.ItemFollowRequestBinding import com.keylesspalace.tusky.databinding.ItemFollowRequestBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.TimelineAccount import com.keylesspalace.tusky.entity.TimelineAccount
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.BindingHolder import com.keylesspalace.tusky.util.BindingHolder
@ -45,17 +43,15 @@ import com.keylesspalace.tusky.util.unsafeLazy
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.viewmodel.AccountsInListViewModel import com.keylesspalace.tusky.viewmodel.AccountsInListViewModel
import com.keylesspalace.tusky.viewmodel.State import com.keylesspalace.tusky.viewmodel.State
import javax.inject.Inject import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
private typealias AccountInfo = Pair<TimelineAccount, Boolean> private typealias AccountInfo = Pair<TimelineAccount, Boolean>
class AccountsInListFragment : DialogFragment(), Injectable { @AndroidEntryPoint
class AccountsInListFragment : DialogFragment() {
@Inject private val viewModel: AccountsInListViewModel by viewModels()
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: AccountsInListViewModel by viewModels { viewModelFactory }
private val binding by viewBinding(FragmentAccountsInListBinding::bind) private val binding by viewBinding(FragmentAccountsInListBinding::bind)
private lateinit var listId: String private lateinit var listId: String

View file

@ -33,6 +33,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import com.google.android.material.color.MaterialColors; import com.google.android.material.color.MaterialColors;
@ -41,7 +42,6 @@ import com.keylesspalace.tusky.adapter.AccountSelectionAdapter;
import com.keylesspalace.tusky.components.login.LoginActivity; import com.keylesspalace.tusky.components.login.LoginActivity;
import com.keylesspalace.tusky.db.entity.AccountEntity; import com.keylesspalace.tusky.db.entity.AccountEntity;
import com.keylesspalace.tusky.db.AccountManager; import com.keylesspalace.tusky.db.AccountManager;
import com.keylesspalace.tusky.di.Injectable;
import com.keylesspalace.tusky.interfaces.AccountSelectionListener; import com.keylesspalace.tusky.interfaces.AccountSelectionListener;
import com.keylesspalace.tusky.settings.AppTheme; import com.keylesspalace.tusky.settings.AppTheme;
import com.keylesspalace.tusky.settings.PrefKeys; import com.keylesspalace.tusky.settings.PrefKeys;
@ -55,7 +55,10 @@ import javax.inject.Inject;
import static com.keylesspalace.tusky.settings.PrefKeys.APP_THEME; import static com.keylesspalace.tusky.settings.PrefKeys.APP_THEME;
public abstract class BaseActivity extends AppCompatActivity implements Injectable { /**
* All activities inheriting from BaseActivity must be annotated with @AndroidEntryPoint
*/
public abstract class BaseActivity extends AppCompatActivity {
public static final String OPEN_WITH_SLIDE_IN = "OPEN_WITH_SLIDE_IN"; public static final String OPEN_WITH_SLIDE_IN = "OPEN_WITH_SLIDE_IN";
@ -65,6 +68,12 @@ public abstract class BaseActivity extends AppCompatActivity implements Injectab
@NonNull @NonNull
public AccountManager accountManager; public AccountManager accountManager;
/**
* Allows overriding the default ViewModelProvider.Factory for testing purposes.
*/
@Nullable
public ViewModelProvider.Factory viewModelProviderFactory = null;
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -152,6 +161,13 @@ public abstract class BaseActivity extends AppCompatActivity implements Injectab
super.attachBaseContext(fontScaleContext); super.attachBaseContext(fontScaleContext);
} }
@NonNull
@Override
public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
final ViewModelProvider.Factory factory = viewModelProviderFactory;
return (factory != null) ? factory : super.getDefaultViewModelProviderFactory();
}
protected boolean requiresLogin() { protected boolean requiresLogin() {
return true; return true;
} }

View file

@ -43,8 +43,6 @@ import com.google.android.material.snackbar.Snackbar
import com.keylesspalace.tusky.adapter.AccountFieldEditAdapter import com.keylesspalace.tusky.adapter.AccountFieldEditAdapter
import com.keylesspalace.tusky.components.instanceinfo.InstanceInfoRepository import com.keylesspalace.tusky.components.instanceinfo.InstanceInfoRepository
import com.keylesspalace.tusky.databinding.ActivityEditProfileBinding import com.keylesspalace.tusky.databinding.ActivityEditProfileBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.util.Error import com.keylesspalace.tusky.util.Error
import com.keylesspalace.tusky.util.Loading import com.keylesspalace.tusky.util.Loading
import com.keylesspalace.tusky.util.Success import com.keylesspalace.tusky.util.Success
@ -57,11 +55,12 @@ import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.sizeDp
import javax.inject.Inject import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class EditProfileActivity : BaseActivity(), Injectable { @AndroidEntryPoint
class EditProfileActivity : BaseActivity() {
companion object { companion object {
const val AVATAR_SIZE = 400 const val AVATAR_SIZE = 400
@ -69,10 +68,7 @@ class EditProfileActivity : BaseActivity(), Injectable {
const val HEADER_HEIGHT = 500 const val HEADER_HEIGHT = 500
} }
@Inject private val viewModel: EditProfileViewModel by viewModels()
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: EditProfileViewModel by viewModels { viewModelFactory }
private val binding by viewBinding(ActivityEditProfileBinding::inflate) private val binding by viewBinding(ActivityEditProfileBinding::inflate)

View file

@ -21,6 +21,7 @@ import android.widget.TextView
import androidx.annotation.RawRes import androidx.annotation.RawRes
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.keylesspalace.tusky.databinding.ActivityLicenseBinding import com.keylesspalace.tusky.databinding.ActivityLicenseBinding
import dagger.hilt.android.AndroidEntryPoint
import java.io.IOException import java.io.IOException
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -28,6 +29,7 @@ import kotlinx.coroutines.withContext
import okio.buffer import okio.buffer
import okio.source import okio.source
@AndroidEntryPoint
class LicenseActivity : BaseActivity() { class LicenseActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {

View file

@ -37,8 +37,6 @@ import com.google.android.material.snackbar.Snackbar
import com.keylesspalace.tusky.databinding.ActivityListsBinding import com.keylesspalace.tusky.databinding.ActivityListsBinding
import com.keylesspalace.tusky.databinding.DialogListBinding import com.keylesspalace.tusky.databinding.DialogListBinding
import com.keylesspalace.tusky.databinding.ItemListBinding import com.keylesspalace.tusky.databinding.ItemListBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.MastoList import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.util.BindingHolder import com.keylesspalace.tusky.util.BindingHolder
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
@ -53,22 +51,15 @@ import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.ERROR_OTHER
import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.INITIAL import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.INITIAL
import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.LOADED import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.LOADED
import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.LOADING import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.LOADING
import dagger.android.DispatchingAndroidInjector import dagger.hilt.android.AndroidEntryPoint
import dagger.android.HasAndroidInjector
import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
// TODO use the ListSelectionFragment (and/or its adapter or binding) here; but keep the LoadingState from here (?) // TODO use the ListSelectionFragment (and/or its adapter or binding) here; but keep the LoadingState from here (?)
class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector { @AndroidEntryPoint
class ListsActivity : BaseActivity() {
@Inject private val viewModel: ListsViewModel by viewModels()
lateinit var viewModelFactory: ViewModelFactory
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
private val viewModel: ListsViewModel by viewModels { viewModelFactory }
private val binding by viewBinding(ActivityListsBinding::inflate) private val binding by viewBinding(ActivityListsBinding::inflate)
@ -287,8 +278,6 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
} }
} }
override fun androidInjector() = dispatchingAndroidInjector
companion object { companion object {
fun newIntent(context: Context) = Intent(context, ListsActivity::class.java) fun newIntent(context: Context) = Intent(context, ListsActivity::class.java)
} }

View file

@ -142,17 +142,17 @@ import com.mikepenz.materialdrawer.util.addItems
import com.mikepenz.materialdrawer.util.addItemsAtPosition import com.mikepenz.materialdrawer.util.addItemsAtPosition
import com.mikepenz.materialdrawer.util.updateBadge import com.mikepenz.materialdrawer.util.updateBadge
import com.mikepenz.materialdrawer.widget.AccountHeaderView import com.mikepenz.materialdrawer.widget.AccountHeaderView
import dagger.android.DispatchingAndroidInjector import dagger.hilt.android.AndroidEntryPoint
import dagger.android.HasAndroidInjector import dagger.hilt.android.migration.OptionalInject
import de.c1710.filemojicompat_ui.helpers.EMOJI_PREFERENCE import de.c1710.filemojicompat_ui.helpers.EMOJI_PREFERENCE
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInjector, MenuProvider { @OptionalInject
@Inject @AndroidEntryPoint
lateinit var androidInjector: DispatchingAndroidInjector<Any> class MainActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider {
@Inject @Inject
lateinit var eventHub: EventHub lateinit var eventHub: EventHub
@ -1215,8 +1215,6 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
override fun getActionButton() = binding.composeButton override fun getActionButton() = binding.composeButton
override fun androidInjector() = androidInjector
companion object { companion object {
const val OPEN_WITH_EXPLODE_ANIMATION = "explode" const val OPEN_WITH_EXPLODE_ANIMATION = "explode"

View file

@ -21,11 +21,12 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.keylesspalace.tusky.components.login.LoginActivity import com.keylesspalace.tusky.components.login.LoginActivity
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
@SuppressLint("CustomSplashScreen") @SuppressLint("CustomSplashScreen")
class SplashActivity : AppCompatActivity(), Injectable { @AndroidEntryPoint
class SplashActivity : AppCompatActivity() {
@Inject @Inject
lateinit var accountManager: AccountManager lateinit var accountManager: AccountManager

View file

@ -37,15 +37,12 @@ import com.keylesspalace.tusky.entity.FilterV1
import com.keylesspalace.tusky.util.isHttpNotFound import com.keylesspalace.tusky.util.isHttpNotFound
import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import dagger.android.DispatchingAndroidInjector import dagger.hilt.android.AndroidEntryPoint
import dagger.android.HasAndroidInjector
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class StatusListActivity : BottomSheetActivity(), HasAndroidInjector { @AndroidEntryPoint
class StatusListActivity : BottomSheetActivity() {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
@Inject @Inject
lateinit var eventHub: EventHub lateinit var eventHub: EventHub
@ -399,8 +396,6 @@ class StatusListActivity : BottomSheetActivity(), HasAndroidInjector {
return true return true
} }
override fun androidInjector() = dispatchingAndroidInjector
companion object { companion object {
private const val EXTRA_KIND = "kind" private const val EXTRA_KIND = "kind"

View file

@ -39,20 +39,19 @@ import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.MainTabsChangedEvent import com.keylesspalace.tusky.appstore.MainTabsChangedEvent
import com.keylesspalace.tusky.components.account.list.ListSelectionFragment import com.keylesspalace.tusky.components.account.list.ListSelectionFragment
import com.keylesspalace.tusky.databinding.ActivityTabPreferenceBinding import com.keylesspalace.tusky.databinding.ActivityTabPreferenceBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.MastoList import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.unsafeLazy
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
import dagger.android.DispatchingAndroidInjector import dagger.hilt.android.AndroidEntryPoint
import dagger.android.HasAndroidInjector
import java.util.regex.Pattern import java.util.regex.Pattern
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class TabPreferenceActivity : BaseActivity(), Injectable, HasAndroidInjector, ItemInteractionListener, ListSelectionFragment.ListSelectionListener { @AndroidEntryPoint
class TabPreferenceActivity : BaseActivity(), ItemInteractionListener, ListSelectionFragment.ListSelectionListener {
@Inject @Inject
lateinit var mastodonApi: MastodonApi lateinit var mastodonApi: MastodonApi
@ -60,9 +59,6 @@ class TabPreferenceActivity : BaseActivity(), Injectable, HasAndroidInjector, It
@Inject @Inject
lateinit var eventHub: EventHub lateinit var eventHub: EventHub
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
private val binding by viewBinding(ActivityTabPreferenceBinding::inflate) private val binding by viewBinding(ActivityTabPreferenceBinding::inflate)
private lateinit var currentTabs: MutableList<TabData> private lateinit var currentTabs: MutableList<TabData>
@ -368,8 +364,6 @@ class TabPreferenceActivity : BaseActivity(), Injectable, HasAndroidInjector, It
} }
} }
override fun androidInjector() = dispatchingAndroidInjector
companion object { companion object {
private const val MIN_TAB_COUNT = 2 private const val MIN_TAB_COUNT = 2
} }

View file

@ -18,12 +18,13 @@ package com.keylesspalace.tusky
import android.app.Application import android.app.Application
import android.content.SharedPreferences import android.content.SharedPreferences
import android.util.Log import android.util.Log
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.Configuration
import androidx.work.Constraints import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import com.keylesspalace.tusky.components.systemnotifications.NotificationHelper import com.keylesspalace.tusky.components.systemnotifications.NotificationHelper
import com.keylesspalace.tusky.di.AppInjector
import com.keylesspalace.tusky.settings.AppTheme import com.keylesspalace.tusky.settings.AppTheme
import com.keylesspalace.tusky.settings.NEW_INSTALL_SCHEMA_VERSION import com.keylesspalace.tusky.settings.NEW_INSTALL_SCHEMA_VERSION
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
@ -32,9 +33,7 @@ import com.keylesspalace.tusky.settings.SCHEMA_VERSION
import com.keylesspalace.tusky.util.LocaleManager import com.keylesspalace.tusky.util.LocaleManager
import com.keylesspalace.tusky.util.setAppNightMode import com.keylesspalace.tusky.util.setAppNightMode
import com.keylesspalace.tusky.worker.PruneCacheWorker import com.keylesspalace.tusky.worker.PruneCacheWorker
import com.keylesspalace.tusky.worker.WorkerFactory import dagger.hilt.android.HiltAndroidApp
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector
import de.c1710.filemojicompat_defaults.DefaultEmojiPackList import de.c1710.filemojicompat_defaults.DefaultEmojiPackList
import de.c1710.filemojicompat_ui.helpers.EmojiPackHelper import de.c1710.filemojicompat_ui.helpers.EmojiPackHelper
import de.c1710.filemojicompat_ui.helpers.EmojiPreference import de.c1710.filemojicompat_ui.helpers.EmojiPreference
@ -43,12 +42,11 @@ import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
import org.conscrypt.Conscrypt import org.conscrypt.Conscrypt
class TuskyApplication : Application(), HasAndroidInjector { @HiltAndroidApp
@Inject class TuskyApplication : Application(), Configuration.Provider {
lateinit var androidInjector: DispatchingAndroidInjector<Any>
@Inject @Inject
lateinit var workerFactory: WorkerFactory lateinit var workerFactory: HiltWorkerFactory
@Inject @Inject
lateinit var localeManager: LocaleManager lateinit var localeManager: LocaleManager
@ -71,8 +69,6 @@ class TuskyApplication : Application(), HasAndroidInjector {
Security.insertProviderAt(Conscrypt.newProvider(), 1) Security.insertProviderAt(Conscrypt.newProvider(), 1)
AppInjector.init(this)
// Migrate shared preference keys and defaults from version to version. // Migrate shared preference keys and defaults from version to version.
val oldVersion = sharedPreferences.getInt( val oldVersion = sharedPreferences.getInt(
PrefKeys.SCHEMA_VERSION, PrefKeys.SCHEMA_VERSION,
@ -95,13 +91,6 @@ class TuskyApplication : Application(), HasAndroidInjector {
NotificationHelper.createWorkerNotificationChannel(this) NotificationHelper.createWorkerNotificationChannel(this)
WorkManager.initialize(
this,
androidx.work.Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
)
// Prune the database every ~ 12 hours when the device is idle. // Prune the database every ~ 12 hours when the device is idle.
val pruneCacheWorker = PeriodicWorkRequestBuilder<PruneCacheWorker>(12, TimeUnit.HOURS) val pruneCacheWorker = PeriodicWorkRequestBuilder<PruneCacheWorker>(12, TimeUnit.HOURS)
.setConstraints(Constraints.Builder().setRequiresDeviceIdle(true).build()) .setConstraints(Constraints.Builder().setRequiresDeviceIdle(true).build())
@ -113,7 +102,10 @@ class TuskyApplication : Application(), HasAndroidInjector {
) )
} }
override fun androidInjector() = androidInjector override val workManagerConfiguration: Configuration
get() = Configuration.Builder()
.setWorkerFactory(workerFactory)
.build()
private fun upgradeSharedPreferences(oldVersion: Int, newVersion: Int) { private fun upgradeSharedPreferences(oldVersion: Int, newVersion: Int) {
Log.d(TAG, "Upgrading shared preferences: $oldVersion -> $newVersion") Log.d(TAG, "Upgrading shared preferences: $oldVersion -> $newVersion")

View file

@ -59,27 +59,22 @@ import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation
import com.keylesspalace.tusky.util.submitAsync import com.keylesspalace.tusky.util.submitAsync
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.viewdata.AttachmentViewData import com.keylesspalace.tusky.viewdata.AttachmentViewData
import dagger.android.DispatchingAndroidInjector import dagger.hilt.android.AndroidEntryPoint
import dagger.android.HasAndroidInjector
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
import java.io.IOException import java.io.IOException
import java.util.Locale import java.util.Locale
import javax.inject.Inject
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
typealias ToolbarVisibilityListener = (isVisible: Boolean) -> Unit typealias ToolbarVisibilityListener = (isVisible: Boolean) -> Unit
@AndroidEntryPoint
class ViewMediaActivity : class ViewMediaActivity :
BaseActivity(), BaseActivity(),
HasAndroidInjector,
ViewImageFragment.PhotoActionsListener, ViewImageFragment.PhotoActionsListener,
ViewVideoFragment.VideoActionsListener { ViewVideoFragment.VideoActionsListener {
@Inject
lateinit var androidInjector: DispatchingAndroidInjector<Any>
private val binding by viewBinding(ActivityViewMediaBinding::inflate) private val binding by viewBinding(ActivityViewMediaBinding::inflate)
val toolbar: View val toolbar: View
@ -361,8 +356,6 @@ class ViewMediaActivity :
} }
} }
override fun androidInjector() = androidInjector
companion object { companion object {
private const val EXTRA_ATTACHMENTS = "attachments" private const val EXTRA_ATTACHMENTS = "attachments"
private const val EXTRA_ATTACHMENT_INDEX = "index" private const val EXTRA_ATTACHMENT_INDEX = "index"

View file

@ -73,7 +73,6 @@ import com.keylesspalace.tusky.components.report.ReportActivity
import com.keylesspalace.tusky.databinding.ActivityAccountBinding import com.keylesspalace.tusky.databinding.ActivityAccountBinding
import com.keylesspalace.tusky.db.DraftsAlert import com.keylesspalace.tusky.db.DraftsAlert
import com.keylesspalace.tusky.db.entity.AccountEntity import com.keylesspalace.tusky.db.entity.AccountEntity
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.Account import com.keylesspalace.tusky.entity.Account
import com.keylesspalace.tusky.entity.Relationship import com.keylesspalace.tusky.entity.Relationship
import com.keylesspalace.tusky.interfaces.AccountSelectionListener import com.keylesspalace.tusky.interfaces.AccountSelectionListener
@ -101,8 +100,7 @@ import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.sizeDp
import dagger.android.DispatchingAndroidInjector import dagger.hilt.android.AndroidEntryPoint
import dagger.android.HasAndroidInjector
import java.text.NumberFormat import java.text.NumberFormat
import java.text.ParseException import java.text.ParseException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@ -111,18 +109,13 @@ import javax.inject.Inject
import kotlin.math.abs import kotlin.math.abs
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider, HasAndroidInjector, LinkListener { @AndroidEntryPoint
class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvider, LinkListener {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
@Inject
lateinit var viewModelFactory: ViewModelFactory
@Inject @Inject
lateinit var draftsAlert: DraftsAlert lateinit var draftsAlert: DraftsAlert
private val viewModel: AccountViewModel by viewModels { viewModelFactory } private val viewModel: AccountViewModel by viewModels()
private val binding: ActivityAccountBinding by viewBinding(ActivityAccountBinding::inflate) private val binding: ActivityAccountBinding by viewBinding(ActivityAccountBinding::inflate)
@ -1143,8 +1136,6 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
return badge return badge
} }
override fun androidInjector() = dispatchingAndroidInjector
companion object { companion object {
private const val KEY_ACCOUNT_ID = "id" private const val KEY_ACCOUNT_ID = "id"

View file

@ -19,6 +19,7 @@ import com.keylesspalace.tusky.util.Loading
import com.keylesspalace.tusky.util.Resource import com.keylesspalace.tusky.util.Resource
import com.keylesspalace.tusky.util.Success import com.keylesspalace.tusky.util.Success
import com.keylesspalace.tusky.util.getDomain import com.keylesspalace.tusky.util.getDomain
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.channels.BufferOverflow
@ -31,6 +32,7 @@ import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@HiltViewModel
class AccountViewModel @Inject constructor( class AccountViewModel @Inject constructor(
private val mastodonApi: MastodonApi, private val mastodonApi: MastodonApi,
private val eventHub: EventHub, private val eventHub: EventHub,

View file

@ -35,30 +35,26 @@ import com.keylesspalace.tusky.ListsActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.FragmentListsListBinding import com.keylesspalace.tusky.databinding.FragmentListsListBinding
import com.keylesspalace.tusky.databinding.ItemListBinding import com.keylesspalace.tusky.databinding.ItemListBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.MastoList import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.util.BindingHolder import com.keylesspalace.tusky.util.BindingHolder
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
import javax.inject.Inject import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class ListSelectionFragment : DialogFragment(), Injectable { @AndroidEntryPoint
class ListSelectionFragment : DialogFragment() {
interface ListSelectionListener { interface ListSelectionListener {
fun onListSelected(list: MastoList) fun onListSelected(list: MastoList)
} }
@Inject private val viewModel: ListsForAccountViewModel by viewModels()
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: ListsForAccountViewModel by viewModels { viewModelFactory }
private var _binding: FragmentListsListBinding? = null private var _binding: FragmentListsListBinding? = null

View file

@ -24,6 +24,7 @@ import at.connyduck.calladapter.networkresult.onSuccess
import at.connyduck.calladapter.networkresult.runCatching import at.connyduck.calladapter.networkresult.runCatching
import com.keylesspalace.tusky.entity.MastoList import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
@ -48,6 +49,7 @@ data class ActionError(
} }
} }
@HiltViewModel
@OptIn(ExperimentalCoroutinesApi::class) @OptIn(ExperimentalCoroutinesApi::class)
class ListsForAccountViewModel @Inject constructor( class ListsForAccountViewModel @Inject constructor(
private val mastodonApi: MastodonApi private val mastodonApi: MastodonApi

View file

@ -35,8 +35,6 @@ import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.ViewMediaActivity import com.keylesspalace.tusky.ViewMediaActivity
import com.keylesspalace.tusky.databinding.FragmentTimelineBinding import com.keylesspalace.tusky.databinding.FragmentTimelineBinding
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.Attachment import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.interfaces.RefreshableFragment import com.keylesspalace.tusky.interfaces.RefreshableFragment
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
@ -49,6 +47,7 @@ import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.sizeDp
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -56,21 +55,18 @@ import kotlinx.coroutines.launch
/** /**
* Fragment with multiple columns of media previews for the specified account. * Fragment with multiple columns of media previews for the specified account.
*/ */
@AndroidEntryPoint
class AccountMediaFragment : class AccountMediaFragment :
Fragment(R.layout.fragment_timeline), Fragment(R.layout.fragment_timeline),
RefreshableFragment, RefreshableFragment,
MenuProvider, MenuProvider {
Injectable {
@Inject
lateinit var viewModelFactory: ViewModelFactory
@Inject @Inject
lateinit var accountManager: AccountManager lateinit var accountManager: AccountManager
private val binding by viewBinding(FragmentTimelineBinding::bind) private val binding by viewBinding(FragmentTimelineBinding::bind)
private val viewModel: AccountMediaViewModel by viewModels { viewModelFactory } private val viewModel: AccountMediaViewModel by viewModels()
private lateinit var adapter: AccountMediaGridAdapter private lateinit var adapter: AccountMediaGridAdapter

View file

@ -24,8 +24,10 @@ import androidx.paging.cachedIn
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.viewdata.AttachmentViewData import com.keylesspalace.tusky.viewdata.AttachmentViewData
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel
class AccountMediaViewModel @Inject constructor( class AccountMediaViewModel @Inject constructor(
accountManager: AccountManager, accountManager: AccountManager,
api: MastodonApi api: MastodonApi

View file

@ -23,14 +23,10 @@ import com.keylesspalace.tusky.BottomSheetActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.ActivityAccountListBinding import com.keylesspalace.tusky.databinding.ActivityAccountListBinding
import com.keylesspalace.tusky.util.getSerializableExtraCompat import com.keylesspalace.tusky.util.getSerializableExtraCompat
import dagger.android.DispatchingAndroidInjector import dagger.hilt.android.AndroidEntryPoint
import dagger.android.HasAndroidInjector
import javax.inject.Inject
class AccountListActivity : BottomSheetActivity(), HasAndroidInjector { @AndroidEntryPoint
class AccountListActivity : BottomSheetActivity() {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
enum class Type { enum class Type {
FOLLOWS, FOLLOWS,
@ -70,8 +66,6 @@ class AccountListActivity : BottomSheetActivity(), HasAndroidInjector {
} }
} }
override fun androidInjector() = dispatchingAndroidInjector
companion object { companion object {
private const val EXTRA_TYPE = "type" private const val EXTRA_TYPE = "type"
private const val EXTRA_ID = "id" private const val EXTRA_ID = "id"

View file

@ -42,7 +42,6 @@ import com.keylesspalace.tusky.components.accountlist.adapter.FollowRequestsHead
import com.keylesspalace.tusky.components.accountlist.adapter.MutesAdapter import com.keylesspalace.tusky.components.accountlist.adapter.MutesAdapter
import com.keylesspalace.tusky.databinding.FragmentAccountListBinding import com.keylesspalace.tusky.databinding.FragmentAccountListBinding
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.Relationship import com.keylesspalace.tusky.entity.Relationship
import com.keylesspalace.tusky.entity.TimelineAccount import com.keylesspalace.tusky.entity.TimelineAccount
import com.keylesspalace.tusky.interfaces.AccountActionListener import com.keylesspalace.tusky.interfaces.AccountActionListener
@ -56,16 +55,17 @@ import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.view.EndlessOnScrollListener import com.keylesspalace.tusky.view.EndlessOnScrollListener
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.Response import retrofit2.Response
@AndroidEntryPoint
class AccountListFragment : class AccountListFragment :
Fragment(R.layout.fragment_account_list), Fragment(R.layout.fragment_account_list),
AccountActionListener, AccountActionListener,
LinkListener, LinkListener {
Injectable {
@Inject @Inject
lateinit var api: MastodonApi lateinit var api: MastodonApi

View file

@ -37,8 +37,6 @@ import com.keylesspalace.tusky.StatusListActivity
import com.keylesspalace.tusky.adapter.EmojiAdapter import com.keylesspalace.tusky.adapter.EmojiAdapter
import com.keylesspalace.tusky.adapter.OnEmojiSelectedListener import com.keylesspalace.tusky.adapter.OnEmojiSelectedListener
import com.keylesspalace.tusky.databinding.ActivityAnnouncementsBinding import com.keylesspalace.tusky.databinding.ActivityAnnouncementsBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.Error import com.keylesspalace.tusky.util.Error
import com.keylesspalace.tusky.util.Loading import com.keylesspalace.tusky.util.Loading
@ -53,20 +51,17 @@ import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.sizeDp
import javax.inject.Inject import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class AnnouncementsActivity : class AnnouncementsActivity :
BottomSheetActivity(), BottomSheetActivity(),
AnnouncementActionListener, AnnouncementActionListener,
OnEmojiSelectedListener, OnEmojiSelectedListener,
MenuProvider, MenuProvider {
Injectable {
@Inject private val viewModel: AnnouncementsViewModel by viewModels()
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: AnnouncementsViewModel by viewModels { viewModelFactory }
private val binding by viewBinding(ActivityAnnouncementsBinding::inflate) private val binding by viewBinding(ActivityAnnouncementsBinding::inflate)

View file

@ -29,12 +29,14 @@ import com.keylesspalace.tusky.util.Error
import com.keylesspalace.tusky.util.Loading import com.keylesspalace.tusky.util.Loading
import com.keylesspalace.tusky.util.Resource import com.keylesspalace.tusky.util.Resource
import com.keylesspalace.tusky.util.Success import com.keylesspalace.tusky.util.Success
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@HiltViewModel
class AnnouncementsViewModel @Inject constructor( class AnnouncementsViewModel @Inject constructor(
private val instanceInfoRepo: InstanceInfoRepository, private val instanceInfoRepo: InstanceInfoRepository,
private val mastodonApi: MastodonApi, private val mastodonApi: MastodonApi,

View file

@ -82,8 +82,6 @@ import com.keylesspalace.tusky.components.instanceinfo.InstanceInfoRepository
import com.keylesspalace.tusky.databinding.ActivityComposeBinding import com.keylesspalace.tusky.databinding.ActivityComposeBinding
import com.keylesspalace.tusky.db.entity.AccountEntity import com.keylesspalace.tusky.db.entity.AccountEntity
import com.keylesspalace.tusky.db.entity.DraftAttachment import com.keylesspalace.tusky.db.entity.DraftAttachment
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.Attachment import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.entity.Emoji import com.keylesspalace.tusky.entity.Emoji
import com.keylesspalace.tusky.entity.NewPoll import com.keylesspalace.tusky.entity.NewPoll
@ -113,11 +111,12 @@ import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.sizeDp
import dagger.hilt.android.AndroidEntryPoint
import dagger.hilt.android.migration.OptionalInject
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.Locale import java.util.Locale
import javax.inject.Inject
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
@ -126,19 +125,17 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@OptionalInject
@AndroidEntryPoint
class ComposeActivity : class ComposeActivity :
BaseActivity(), BaseActivity(),
ComposeOptionsListener, ComposeOptionsListener,
ComposeAutoCompleteAdapter.AutocompletionProvider, ComposeAutoCompleteAdapter.AutocompletionProvider,
OnEmojiSelectedListener, OnEmojiSelectedListener,
Injectable,
OnReceiveContentListener, OnReceiveContentListener,
ComposeScheduleView.OnTimeSetListener, ComposeScheduleView.OnTimeSetListener,
CaptionDialog.Listener { CaptionDialog.Listener {
@Inject
lateinit var viewModelFactory: ViewModelFactory
private lateinit var composeOptionsBehavior: BottomSheetBehavior<*> private lateinit var composeOptionsBehavior: BottomSheetBehavior<*>
private lateinit var addMediaBehavior: BottomSheetBehavior<*> private lateinit var addMediaBehavior: BottomSheetBehavior<*>
private lateinit var emojiBehavior: BottomSheetBehavior<*> private lateinit var emojiBehavior: BottomSheetBehavior<*>
@ -155,7 +152,7 @@ class ComposeActivity :
var maximumTootCharacters = InstanceInfoRepository.DEFAULT_CHARACTER_LIMIT var maximumTootCharacters = InstanceInfoRepository.DEFAULT_CHARACTER_LIMIT
var charactersReservedPerUrl = InstanceInfoRepository.DEFAULT_CHARACTERS_RESERVED_PER_URL var charactersReservedPerUrl = InstanceInfoRepository.DEFAULT_CHARACTERS_RESERVED_PER_URL
private val viewModel: ComposeViewModel by viewModels { viewModelFactory } private val viewModel: ComposeViewModel by viewModels()
private val binding by viewBinding(ActivityComposeBinding::inflate) private val binding by viewBinding(ActivityComposeBinding::inflate)

View file

@ -75,6 +75,7 @@ class ComposeAutoCompleteAdapter(
return filterResults return filterResults
} }
@Suppress("UNCHECKED_CAST")
override fun publishResults(constraint: CharSequence?, results: FilterResults) { override fun publishResults(constraint: CharSequence?, results: FilterResults) {
if (results.count > 0) { if (results.count > 0) {
resultList = results.values as List<AutocompleteResult> resultList = results.values as List<AutocompleteResult>

View file

@ -38,6 +38,7 @@ import com.keylesspalace.tusky.service.MediaToSend
import com.keylesspalace.tusky.service.ServiceClient import com.keylesspalace.tusky.service.ServiceClient
import com.keylesspalace.tusky.service.StatusToSend import com.keylesspalace.tusky.service.StatusToSend
import com.keylesspalace.tusky.util.randomAlphanumericString import com.keylesspalace.tusky.util.randomAlphanumericString
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.channels.BufferOverflow
@ -56,6 +57,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@HiltViewModel
class ComposeViewModel @Inject constructor( class ComposeViewModel @Inject constructor(
private val api: MastodonApi, private val api: MastodonApi,
private val accountManager: AccountManager, private val accountManager: AccountManager,

View file

@ -36,6 +36,7 @@ import com.keylesspalace.tusky.util.getImageSquarePixels
import com.keylesspalace.tusky.util.getMediaSize import com.keylesspalace.tusky.util.getMediaSize
import com.keylesspalace.tusky.util.getServerErrorMessage import com.keylesspalace.tusky.util.getServerErrorMessage
import com.keylesspalace.tusky.util.randomAlphanumericString import com.keylesspalace.tusky.util.randomAlphanumericString
import dagger.hilt.android.qualifiers.ApplicationContext
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import javax.inject.Inject import javax.inject.Inject
@ -94,7 +95,7 @@ class UploadServerError(val errorMessage: String) : Exception()
@Singleton @Singleton
class MediaUploader @Inject constructor( class MediaUploader @Inject constructor(
private val context: Context, @ApplicationContext private val context: Context,
private val mediaUploadApi: MediaUploadApi private val mediaUploadApi: MediaUploadApi
) { ) {

View file

@ -45,8 +45,6 @@ import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.PreferenceChangedEvent import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
import com.keylesspalace.tusky.components.account.AccountActivity import com.keylesspalace.tusky.components.account.AccountActivity
import com.keylesspalace.tusky.databinding.FragmentTimelineBinding import com.keylesspalace.tusky.databinding.FragmentTimelineBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.fragment.SFragment import com.keylesspalace.tusky.fragment.SFragment
import com.keylesspalace.tusky.interfaces.ActionButtonActivity import com.keylesspalace.tusky.interfaces.ActionButtonActivity
import com.keylesspalace.tusky.interfaces.ReselectableFragment import com.keylesspalace.tusky.interfaces.ReselectableFragment
@ -63,6 +61,7 @@ import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.sizeDp
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlin.time.DurationUnit import kotlin.time.DurationUnit
import kotlin.time.toDuration import kotlin.time.toDuration
@ -70,20 +69,17 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class ConversationsFragment : class ConversationsFragment :
SFragment(), SFragment(),
StatusActionListener, StatusActionListener,
Injectable,
ReselectableFragment, ReselectableFragment,
MenuProvider { MenuProvider {
@Inject
lateinit var viewModelFactory: ViewModelFactory
@Inject @Inject
lateinit var eventHub: EventHub lateinit var eventHub: EventHub
private val viewModel: ConversationsViewModel by viewModels { viewModelFactory } private val viewModel: ConversationsViewModel by viewModels()
private val binding by viewBinding(FragmentTimelineBinding::bind) private val binding by viewBinding(FragmentTimelineBinding::bind)

View file

@ -29,10 +29,12 @@ import com.keylesspalace.tusky.db.AppDatabase
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.usecase.TimelineCases import com.keylesspalace.tusky.usecase.TimelineCases
import com.keylesspalace.tusky.util.EmptyPagingSource import com.keylesspalace.tusky.util.EmptyPagingSource
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@HiltViewModel
class ConversationsViewModel @Inject constructor( class ConversationsViewModel @Inject constructor(
private val timelineCases: TimelineCases, private val timelineCases: TimelineCases,
private val database: AppDatabase, private val database: AppDatabase,

View file

@ -4,14 +4,10 @@ import android.os.Bundle
import com.keylesspalace.tusky.BaseActivity import com.keylesspalace.tusky.BaseActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.ActivityAccountListBinding import com.keylesspalace.tusky.databinding.ActivityAccountListBinding
import dagger.android.DispatchingAndroidInjector import dagger.hilt.android.AndroidEntryPoint
import dagger.android.HasAndroidInjector
import javax.inject.Inject
class DomainBlocksActivity : BaseActivity(), HasAndroidInjector { @AndroidEntryPoint
class DomainBlocksActivity : BaseActivity() {
@Inject
lateinit var androidInjector: DispatchingAndroidInjector<Any>
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -30,6 +26,4 @@ class DomainBlocksActivity : BaseActivity(), HasAndroidInjector {
.replace(R.id.fragment_container, DomainBlocksFragment()) .replace(R.id.fragment_container, DomainBlocksFragment())
.commit() .commit()
} }
override fun androidInjector() = androidInjector
} }

View file

@ -12,24 +12,20 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.FragmentDomainBlocksBinding import com.keylesspalace.tusky.databinding.FragmentDomainBlocksBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
import javax.inject.Inject import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class DomainBlocksFragment : Fragment(R.layout.fragment_domain_blocks), Injectable { @AndroidEntryPoint
class DomainBlocksFragment : Fragment(R.layout.fragment_domain_blocks) {
@Inject
lateinit var viewModelFactory: ViewModelFactory
private val binding by viewBinding(FragmentDomainBlocksBinding::bind) private val binding by viewBinding(FragmentDomainBlocksBinding::bind)
private val viewModel: DomainBlocksViewModel by viewModels { viewModelFactory } private val viewModel: DomainBlocksViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val adapter = DomainBlocksAdapter(viewModel::unblock) val adapter = DomainBlocksAdapter(viewModel::unblock)

View file

@ -8,12 +8,14 @@ import androidx.paging.cachedIn
import at.connyduck.calladapter.networkresult.fold import at.connyduck.calladapter.networkresult.fold
import at.connyduck.calladapter.networkresult.onFailure import at.connyduck.calladapter.networkresult.onFailure
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@HiltViewModel
class DomainBlocksViewModel @Inject constructor( class DomainBlocksViewModel @Inject constructor(
private val repo: DomainBlocksRepository private val repo: DomainBlocksRepository
) : ViewModel() { ) : ViewModel() {

View file

@ -29,6 +29,7 @@ import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.entity.NewPoll import com.keylesspalace.tusky.entity.NewPoll
import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.util.copyToFile import com.keylesspalace.tusky.util.copyToFile
import dagger.hilt.android.qualifiers.ApplicationContext
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@ -43,7 +44,7 @@ import okio.buffer
import okio.sink import okio.sink
class DraftHelper @Inject constructor( class DraftHelper @Inject constructor(
val context: Context, @ApplicationContext val context: Context,
private val okHttpClient: OkHttpClient, private val okHttpClient: OkHttpClient,
db: AppDatabase db: AppDatabase
) { ) {

View file

@ -34,23 +34,21 @@ import com.keylesspalace.tusky.components.compose.ComposeActivity
import com.keylesspalace.tusky.databinding.ActivityDraftsBinding import com.keylesspalace.tusky.databinding.ActivityDraftsBinding
import com.keylesspalace.tusky.db.DraftsAlert import com.keylesspalace.tusky.db.DraftsAlert
import com.keylesspalace.tusky.db.entity.DraftEntity import com.keylesspalace.tusky.db.entity.DraftEntity
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.util.isHttpNotFound import com.keylesspalace.tusky.util.isHttpNotFound
import com.keylesspalace.tusky.util.parseAsMastodonHtml import com.keylesspalace.tusky.util.parseAsMastodonHtml
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class DraftsActivity : BaseActivity(), DraftActionListener { class DraftsActivity : BaseActivity(), DraftActionListener {
@Inject
lateinit var viewModelFactory: ViewModelFactory
@Inject @Inject
lateinit var draftsAlert: DraftsAlert lateinit var draftsAlert: DraftsAlert
private val viewModel: DraftsViewModel by viewModels { viewModelFactory } private val viewModel: DraftsViewModel by viewModels()
private lateinit var binding: ActivityDraftsBinding private lateinit var binding: ActivityDraftsBinding
private lateinit var bottomSheet: BottomSheetBehavior<LinearLayout> private lateinit var bottomSheet: BottomSheetBehavior<LinearLayout>

View file

@ -26,9 +26,11 @@ import com.keylesspalace.tusky.db.AppDatabase
import com.keylesspalace.tusky.db.entity.DraftEntity import com.keylesspalace.tusky.db.entity.DraftEntity
import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@HiltViewModel
class DraftsViewModel @Inject constructor( class DraftsViewModel @Inject constructor(
val database: AppDatabase, val database: AppDatabase,
val accountManager: AccountManager, val accountManager: AccountManager,

View file

@ -21,7 +21,6 @@ import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.FilterUpdatedEvent import com.keylesspalace.tusky.appstore.FilterUpdatedEvent
import com.keylesspalace.tusky.databinding.ActivityEditFilterBinding import com.keylesspalace.tusky.databinding.ActivityEditFilterBinding
import com.keylesspalace.tusky.databinding.DialogFilterBinding import com.keylesspalace.tusky.databinding.DialogFilterBinding
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.Filter import com.keylesspalace.tusky.entity.Filter
import com.keylesspalace.tusky.entity.FilterKeyword import com.keylesspalace.tusky.entity.FilterKeyword
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
@ -29,10 +28,12 @@ import com.keylesspalace.tusky.util.getParcelableExtraCompat
import com.keylesspalace.tusky.util.isHttpNotFound import com.keylesspalace.tusky.util.isHttpNotFound
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
import dagger.hilt.android.AndroidEntryPoint
import java.util.Date import java.util.Date
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class EditFilterActivity : BaseActivity() { class EditFilterActivity : BaseActivity() {
@Inject @Inject
lateinit var api: MastodonApi lateinit var api: MastodonApi
@ -40,11 +41,8 @@ class EditFilterActivity : BaseActivity() {
@Inject @Inject
lateinit var eventHub: EventHub lateinit var eventHub: EventHub
@Inject
lateinit var viewModelFactory: ViewModelFactory
private val binding by viewBinding(ActivityEditFilterBinding::inflate) private val binding by viewBinding(ActivityEditFilterBinding::inflate)
private val viewModel: EditFilterViewModel by viewModels { viewModelFactory } private val viewModel: EditFilterViewModel by viewModels()
private lateinit var filter: Filter private lateinit var filter: Filter
private var originalFilter: Filter? = null private var originalFilter: Filter? = null

View file

@ -9,12 +9,14 @@ import com.keylesspalace.tusky.entity.Filter
import com.keylesspalace.tusky.entity.FilterKeyword import com.keylesspalace.tusky.entity.FilterKeyword
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.isHttpNotFound import com.keylesspalace.tusky.util.isHttpNotFound
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@HiltViewModel
class EditFilterViewModel @Inject constructor(val api: MastodonApi, val eventHub: EventHub) : ViewModel() { class EditFilterViewModel @Inject constructor(val api: MastodonApi, val eventHub: EventHub) : ViewModel() {
private var originalFilter: Filter? = null private var originalFilter: Filter? = null

View file

@ -8,22 +8,20 @@ import androidx.lifecycle.lifecycleScope
import com.keylesspalace.tusky.BaseActivity import com.keylesspalace.tusky.BaseActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.ActivityFiltersBinding import com.keylesspalace.tusky.databinding.ActivityFiltersBinding
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.Filter import com.keylesspalace.tusky.entity.Filter
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
import javax.inject.Inject import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class FiltersActivity : BaseActivity(), FiltersListener { class FiltersActivity : BaseActivity(), FiltersListener {
@Inject
lateinit var viewModelFactory: ViewModelFactory
private val binding by viewBinding(ActivityFiltersBinding::inflate) private val binding by viewBinding(ActivityFiltersBinding::inflate)
private val viewModel: FiltersViewModel by viewModels { viewModelFactory } private val viewModel: FiltersViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)

View file

@ -10,12 +10,14 @@ import com.keylesspalace.tusky.appstore.PreferenceChangedEvent
import com.keylesspalace.tusky.entity.Filter import com.keylesspalace.tusky.entity.Filter
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.isHttpNotFound import com.keylesspalace.tusky.util.isHttpNotFound
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@HiltViewModel
class FiltersViewModel @Inject constructor( class FiltersViewModel @Inject constructor(
private val api: MastodonApi, private val api: MastodonApi,
private val eventHub: EventHub private val eventHub: EventHub

View file

@ -21,7 +21,6 @@ import com.keylesspalace.tusky.BaseActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.components.compose.ComposeAutoCompleteAdapter import com.keylesspalace.tusky.components.compose.ComposeAutoCompleteAdapter
import com.keylesspalace.tusky.databinding.ActivityFollowedTagsBinding import com.keylesspalace.tusky.databinding.ActivityFollowedTagsBinding
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.interfaces.HashtagActionListener import com.keylesspalace.tusky.interfaces.HashtagActionListener
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
@ -29,10 +28,12 @@ import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class FollowedTagsActivity : class FollowedTagsActivity :
BaseActivity(), BaseActivity(),
HashtagActionListener, HashtagActionListener,
@ -40,14 +41,11 @@ class FollowedTagsActivity :
@Inject @Inject
lateinit var api: MastodonApi lateinit var api: MastodonApi
@Inject
lateinit var viewModelFactory: ViewModelFactory
@Inject @Inject
lateinit var sharedPreferences: SharedPreferences lateinit var sharedPreferences: SharedPreferences
private val binding by viewBinding(ActivityFollowedTagsBinding::inflate) private val binding by viewBinding(ActivityFollowedTagsBinding::inflate)
private val viewModel: FollowedTagsViewModel by viewModels { viewModelFactory } private val viewModel: FollowedTagsViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)

View file

@ -10,15 +10,16 @@ import androidx.paging.cachedIn
import at.connyduck.calladapter.networkresult.fold import at.connyduck.calladapter.networkresult.fold
import com.keylesspalace.tusky.components.compose.ComposeAutoCompleteAdapter import com.keylesspalace.tusky.components.compose.ComposeAutoCompleteAdapter
import com.keylesspalace.tusky.components.search.SearchType import com.keylesspalace.tusky.components.search.SearchType
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.HashTag import com.keylesspalace.tusky.entity.HashTag
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@HiltViewModel
class FollowedTagsViewModel @Inject constructor( class FollowedTagsViewModel @Inject constructor(
private val api: MastodonApi private val api: MastodonApi
) : ViewModel(), Injectable { ) : ViewModel() {
val tags: MutableList<HashTag> = mutableListOf() val tags: MutableList<HashTag> = mutableListOf()
var nextKey: String? = null var nextKey: String? = null
var currentSource: FollowedTagsPagingSource? = null var currentSource: FollowedTagsPagingSource? = null

View file

@ -34,7 +34,6 @@ import com.keylesspalace.tusky.BuildConfig
import com.keylesspalace.tusky.MainActivity import com.keylesspalace.tusky.MainActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.ActivityLoginBinding import com.keylesspalace.tusky.databinding.ActivityLoginBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.AccessToken import com.keylesspalace.tusky.entity.AccessToken
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.getNonNullString import com.keylesspalace.tusky.util.getNonNullString
@ -42,12 +41,14 @@ import com.keylesspalace.tusky.util.openLinkInCustomTab
import com.keylesspalace.tusky.util.rickRoll import com.keylesspalace.tusky.util.rickRoll
import com.keylesspalace.tusky.util.shouldRickRoll import com.keylesspalace.tusky.util.shouldRickRoll
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import okhttp3.HttpUrl import okhttp3.HttpUrl
/** Main login page, the first thing that users see. Has prompt for instance and login button. */ /** Main login page, the first thing that users see. Has prompt for instance and login button. */
class LoginActivity : BaseActivity(), Injectable { @AndroidEntryPoint
class LoginActivity : BaseActivity() {
@Inject @Inject
lateinit var mastodonApi: MastodonApi lateinit var mastodonApi: MastodonApi

View file

@ -39,13 +39,11 @@ import com.keylesspalace.tusky.BaseActivity
import com.keylesspalace.tusky.BuildConfig import com.keylesspalace.tusky.BuildConfig
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.ActivityLoginWebviewBinding import com.keylesspalace.tusky.databinding.ActivityLoginWebviewBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.util.getParcelableExtraCompat import com.keylesspalace.tusky.util.getParcelableExtraCompat
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
import javax.inject.Inject import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@ -102,13 +100,11 @@ sealed interface LoginResult : Parcelable {
} }
/** Activity to do Oauth process using WebView. */ /** Activity to do Oauth process using WebView. */
class LoginWebViewActivity : BaseActivity(), Injectable { @AndroidEntryPoint
class LoginWebViewActivity : BaseActivity() {
private val binding by viewBinding(ActivityLoginWebviewBinding::inflate) private val binding by viewBinding(ActivityLoginWebviewBinding::inflate)
@Inject private val viewModel: LoginWebViewViewModel by viewModels()
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: LoginWebViewViewModel by viewModels { viewModelFactory }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)

View file

@ -21,11 +21,13 @@ import androidx.lifecycle.viewModelScope
import at.connyduck.calladapter.networkresult.fold import at.connyduck.calladapter.networkresult.fold
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.isHttpNotFound import com.keylesspalace.tusky.util.isHttpNotFound
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@HiltViewModel
class LoginWebViewViewModel @Inject constructor( class LoginWebViewViewModel @Inject constructor(
private val api: MastodonApi private val api: MastodonApi
) : ViewModel() { ) : ViewModel() {

View file

@ -52,8 +52,6 @@ import com.keylesspalace.tusky.components.preference.PreferencesFragment.Reading
import com.keylesspalace.tusky.components.systemnotifications.NotificationHelper import com.keylesspalace.tusky.components.systemnotifications.NotificationHelper
import com.keylesspalace.tusky.databinding.FragmentTimelineNotificationsBinding import com.keylesspalace.tusky.databinding.FragmentTimelineNotificationsBinding
import com.keylesspalace.tusky.databinding.NotificationsFilterBinding import com.keylesspalace.tusky.databinding.NotificationsFilterBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.Notification import com.keylesspalace.tusky.entity.Notification
import com.keylesspalace.tusky.fragment.SFragment import com.keylesspalace.tusky.fragment.SFragment
import com.keylesspalace.tusky.interfaces.AccountActionListener import com.keylesspalace.tusky.interfaces.AccountActionListener
@ -72,6 +70,7 @@ import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.viewdata.AttachmentViewData import com.keylesspalace.tusky.viewdata.AttachmentViewData
import com.keylesspalace.tusky.viewdata.NotificationViewData import com.keylesspalace.tusky.viewdata.NotificationViewData
import com.keylesspalace.tusky.viewdata.TranslationViewData import com.keylesspalace.tusky.viewdata.TranslationViewData
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlin.time.DurationUnit import kotlin.time.DurationUnit
import kotlin.time.toDuration import kotlin.time.toDuration
@ -79,6 +78,7 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class NotificationsFragment : class NotificationsFragment :
SFragment(), SFragment(),
SwipeRefreshLayout.OnRefreshListener, SwipeRefreshLayout.OnRefreshListener,
@ -86,11 +86,7 @@ class NotificationsFragment :
NotificationActionListener, NotificationActionListener,
AccountActionListener, AccountActionListener,
MenuProvider, MenuProvider,
ReselectableFragment, ReselectableFragment {
Injectable {
@Inject
lateinit var viewModelFactory: ViewModelFactory
@Inject @Inject
lateinit var preferences: SharedPreferences lateinit var preferences: SharedPreferences
@ -100,7 +96,7 @@ class NotificationsFragment :
private val binding by viewBinding(FragmentTimelineNotificationsBinding::bind) private val binding by viewBinding(FragmentTimelineNotificationsBinding::bind)
private val viewModel: NotificationsViewModel by viewModels { viewModelFactory } private val viewModel: NotificationsViewModel by viewModels()
private lateinit var adapter: NotificationsPagingAdapter private lateinit var adapter: NotificationsPagingAdapter

View file

@ -51,6 +51,7 @@ import com.keylesspalace.tusky.util.serialize
import com.keylesspalace.tusky.viewdata.NotificationViewData import com.keylesspalace.tusky.viewdata.NotificationViewData
import com.keylesspalace.tusky.viewdata.StatusViewData import com.keylesspalace.tusky.viewdata.StatusViewData
import com.keylesspalace.tusky.viewdata.TranslationViewData import com.keylesspalace.tusky.viewdata.TranslationViewData
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
@ -64,6 +65,7 @@ import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import retrofit2.HttpException import retrofit2.HttpException
@HiltViewModel
class NotificationsViewModel @Inject constructor( class NotificationsViewModel @Inject constructor(
private val timelineCases: TimelineCases, private val timelineCases: TimelineCases,
private val api: MastodonApi, private val api: MastodonApi,

View file

@ -38,7 +38,6 @@ import com.keylesspalace.tusky.components.followedtags.FollowedTagsActivity
import com.keylesspalace.tusky.components.login.LoginActivity import com.keylesspalace.tusky.components.login.LoginActivity
import com.keylesspalace.tusky.components.systemnotifications.currentAccountNeedsMigration import com.keylesspalace.tusky.components.systemnotifications.currentAccountNeedsMigration
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.Account import com.keylesspalace.tusky.entity.Account
import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
@ -59,10 +58,12 @@ import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeRes import com.mikepenz.iconics.utils.sizeRes
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class AccountPreferencesFragment : PreferenceFragmentCompat(), Injectable { @AndroidEntryPoint
class AccountPreferencesFragment : PreferenceFragmentCompat() {
@Inject @Inject
lateinit var accountManager: AccountManager lateinit var accountManager: AccountManager

View file

@ -21,14 +21,15 @@ import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.components.systemnotifications.NotificationHelper import com.keylesspalace.tusky.components.systemnotifications.NotificationHelper
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.db.entity.AccountEntity import com.keylesspalace.tusky.db.entity.AccountEntity
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.settings.makePreferenceScreen import com.keylesspalace.tusky.settings.makePreferenceScreen
import com.keylesspalace.tusky.settings.preferenceCategory import com.keylesspalace.tusky.settings.preferenceCategory
import com.keylesspalace.tusky.settings.switchPreference import com.keylesspalace.tusky.settings.switchPreference
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
class NotificationPreferencesFragment : PreferenceFragmentCompat(), Injectable { @AndroidEntryPoint
class NotificationPreferencesFragment : PreferenceFragmentCompat() {
@Inject @Inject
lateinit var accountManager: AccountManager lateinit var accountManager: AccountManager

View file

@ -39,23 +39,19 @@ import com.keylesspalace.tusky.settings.PrefKeys.APP_THEME
import com.keylesspalace.tusky.util.getNonNullString import com.keylesspalace.tusky.util.getNonNullString
import com.keylesspalace.tusky.util.setAppNightMode import com.keylesspalace.tusky.util.setAppNightMode
import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation
import dagger.android.DispatchingAndroidInjector import dagger.hilt.android.AndroidEntryPoint
import dagger.android.HasAndroidInjector
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class PreferencesActivity : class PreferencesActivity :
BaseActivity(), BaseActivity(),
SharedPreferences.OnSharedPreferenceChangeListener, SharedPreferences.OnSharedPreferenceChangeListener,
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback, PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
HasAndroidInjector {
@Inject @Inject
lateinit var eventHub: EventHub lateinit var eventHub: EventHub
@Inject
lateinit var androidInjector: DispatchingAndroidInjector<Any>
private val restartActivitiesOnBackPressedCallback = object : OnBackPressedCallback(false) { private val restartActivitiesOnBackPressedCallback = object : OnBackPressedCallback(false) {
override fun handleOnBackPressed() { override fun handleOnBackPressed() {
/* Switching themes won't actually change the theme of activities on the back stack. /* Switching themes won't actually change the theme of activities on the back stack.
@ -171,8 +167,6 @@ class PreferencesActivity :
} }
} }
override fun androidInjector() = androidInjector
companion object { companion object {
@Suppress("unused") @Suppress("unused")
private const val TAG = "PreferencesActivity" private const val TAG = "PreferencesActivity"

View file

@ -20,7 +20,6 @@ import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.Notification import com.keylesspalace.tusky.entity.Notification
import com.keylesspalace.tusky.settings.AppTheme import com.keylesspalace.tusky.settings.AppTheme
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
@ -38,10 +37,12 @@ import com.keylesspalace.tusky.util.serialize
import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.unsafeLazy
import com.mikepenz.iconics.IconicsDrawable import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import dagger.hilt.android.AndroidEntryPoint
import de.c1710.filemojicompat_ui.views.picker.preference.EmojiPickerPreference import de.c1710.filemojicompat_ui.views.picker.preference.EmojiPickerPreference
import javax.inject.Inject import javax.inject.Inject
class PreferencesFragment : PreferenceFragmentCompat(), Injectable { @AndroidEntryPoint
class PreferencesFragment : PreferenceFragmentCompat() {
@Inject @Inject
lateinit var accountManager: AccountManager lateinit var accountManager: AccountManager

View file

@ -22,15 +22,16 @@ import android.view.ViewGroup
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import com.google.android.material.color.MaterialColors import com.google.android.material.color.MaterialColors
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.settings.AccountPreferenceDataStore import com.keylesspalace.tusky.settings.AccountPreferenceDataStore
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.settings.makePreferenceScreen import com.keylesspalace.tusky.settings.makePreferenceScreen
import com.keylesspalace.tusky.settings.preferenceCategory import com.keylesspalace.tusky.settings.preferenceCategory
import com.keylesspalace.tusky.settings.switchPreference import com.keylesspalace.tusky.settings.switchPreference
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
class TabFilterPreferencesFragment : PreferenceFragmentCompat(), Injectable { @AndroidEntryPoint
class TabFilterPreferencesFragment : PreferenceFragmentCompat() {
@Inject @Inject
lateinit var accountPreferenceDataStore: AccountPreferenceDataStore lateinit var accountPreferenceDataStore: AccountPreferenceDataStore

View file

@ -24,22 +24,14 @@ import com.keylesspalace.tusky.BottomSheetActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.components.report.adapter.ReportPagerAdapter import com.keylesspalace.tusky.components.report.adapter.ReportPagerAdapter
import com.keylesspalace.tusky.databinding.ActivityReportBinding import com.keylesspalace.tusky.databinding.ActivityReportBinding
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import dagger.android.DispatchingAndroidInjector import dagger.hilt.android.AndroidEntryPoint
import dagger.android.HasAndroidInjector
import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class ReportActivity : BottomSheetActivity(), HasAndroidInjector { @AndroidEntryPoint
class ReportActivity : BottomSheetActivity() {
@Inject private val viewModel: ReportViewModel by viewModels()
lateinit var androidInjector: DispatchingAndroidInjector<Any>
@Inject
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: ReportViewModel by viewModels { viewModelFactory }
private val binding by viewBinding(ActivityReportBinding::inflate) private val binding by viewBinding(ActivityReportBinding::inflate)
@ -149,6 +141,4 @@ class ReportActivity : BottomSheetActivity(), HasAndroidInjector {
putExtra(STATUS_ID, statusId) putExtra(STATUS_ID, statusId)
} }
} }
override fun androidInjector() = androidInjector
} }

View file

@ -35,7 +35,9 @@ import com.keylesspalace.tusky.util.Loading
import com.keylesspalace.tusky.util.Resource import com.keylesspalace.tusky.util.Resource
import com.keylesspalace.tusky.util.Success import com.keylesspalace.tusky.util.Success
import com.keylesspalace.tusky.util.toViewData import com.keylesspalace.tusky.util.toViewData
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -45,6 +47,8 @@ import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@HiltViewModel
@OptIn(ExperimentalCoroutinesApi::class)
class ReportViewModel @Inject constructor( class ReportViewModel @Inject constructor(
private val mastodonApi: MastodonApi, private val mastodonApi: MastodonApi,
private val eventHub: EventHub private val eventHub: EventHub

View file

@ -24,21 +24,17 @@ import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.components.report.ReportViewModel import com.keylesspalace.tusky.components.report.ReportViewModel
import com.keylesspalace.tusky.components.report.Screen import com.keylesspalace.tusky.components.report.Screen
import com.keylesspalace.tusky.databinding.FragmentReportDoneBinding import com.keylesspalace.tusky.databinding.FragmentReportDoneBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.util.Loading import com.keylesspalace.tusky.util.Loading
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import javax.inject.Inject import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class ReportDoneFragment : Fragment(R.layout.fragment_report_done), Injectable { @AndroidEntryPoint
class ReportDoneFragment : Fragment(R.layout.fragment_report_done) {
@Inject private val viewModel: ReportViewModel by activityViewModels()
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: ReportViewModel by activityViewModels { viewModelFactory }
private val binding by viewBinding(FragmentReportDoneBinding::bind) private val binding by viewBinding(FragmentReportDoneBinding::bind)

View file

@ -26,24 +26,20 @@ import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.components.report.ReportViewModel import com.keylesspalace.tusky.components.report.ReportViewModel
import com.keylesspalace.tusky.components.report.Screen import com.keylesspalace.tusky.components.report.Screen
import com.keylesspalace.tusky.databinding.FragmentReportNoteBinding import com.keylesspalace.tusky.databinding.FragmentReportNoteBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.util.Error import com.keylesspalace.tusky.util.Error
import com.keylesspalace.tusky.util.Loading import com.keylesspalace.tusky.util.Loading
import com.keylesspalace.tusky.util.Success import com.keylesspalace.tusky.util.Success
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import dagger.hilt.android.AndroidEntryPoint
import java.io.IOException import java.io.IOException
import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class ReportNoteFragment : Fragment(R.layout.fragment_report_note), Injectable { @AndroidEntryPoint
class ReportNoteFragment : Fragment(R.layout.fragment_report_note) {
@Inject private val viewModel: ReportViewModel by activityViewModels()
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: ReportViewModel by activityViewModels { viewModelFactory }
private val binding by viewBinding(FragmentReportNoteBinding::bind) private val binding by viewBinding(FragmentReportNoteBinding::bind)

View file

@ -45,8 +45,6 @@ import com.keylesspalace.tusky.components.report.adapter.AdapterHandler
import com.keylesspalace.tusky.components.report.adapter.StatusesAdapter import com.keylesspalace.tusky.components.report.adapter.StatusesAdapter
import com.keylesspalace.tusky.databinding.FragmentReportStatusesBinding import com.keylesspalace.tusky.databinding.FragmentReportStatusesBinding
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.Attachment import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
@ -59,24 +57,22 @@ import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.sizeDp
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class ReportStatusesFragment : class ReportStatusesFragment :
Fragment(R.layout.fragment_report_statuses), Fragment(R.layout.fragment_report_statuses),
Injectable,
OnRefreshListener, OnRefreshListener,
MenuProvider, MenuProvider,
AdapterHandler { AdapterHandler {
@Inject
lateinit var viewModelFactory: ViewModelFactory
@Inject @Inject
lateinit var accountManager: AccountManager lateinit var accountManager: AccountManager
private val viewModel: ReportViewModel by activityViewModels { viewModelFactory } private val viewModel: ReportViewModel by activityViewModels()
private val binding by viewBinding(FragmentReportStatusesBinding::bind) private val binding by viewBinding(FragmentReportStatusesBinding::bind)

View file

@ -35,8 +35,6 @@ import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.StatusScheduledEvent import com.keylesspalace.tusky.appstore.StatusScheduledEvent
import com.keylesspalace.tusky.components.compose.ComposeActivity import com.keylesspalace.tusky.components.compose.ComposeActivity
import com.keylesspalace.tusky.databinding.ActivityScheduledStatusBinding import com.keylesspalace.tusky.databinding.ActivityScheduledStatusBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.ScheduledStatus import com.keylesspalace.tusky.entity.ScheduledStatus
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show import com.keylesspalace.tusky.util.show
@ -45,23 +43,21 @@ import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.sizeDp
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class ScheduledStatusActivity : class ScheduledStatusActivity :
BaseActivity(), BaseActivity(),
ScheduledStatusActionListener, ScheduledStatusActionListener,
MenuProvider, MenuProvider {
Injectable {
@Inject
lateinit var viewModelFactory: ViewModelFactory
@Inject @Inject
lateinit var eventHub: EventHub lateinit var eventHub: EventHub
private val viewModel: ScheduledStatusViewModel by viewModels { viewModelFactory } private val viewModel: ScheduledStatusViewModel by viewModels()
private val binding by viewBinding(ActivityScheduledStatusBinding::inflate) private val binding by viewBinding(ActivityScheduledStatusBinding::inflate)

View file

@ -25,9 +25,11 @@ import at.connyduck.calladapter.networkresult.fold
import com.keylesspalace.tusky.appstore.EventHub import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.entity.ScheduledStatus import com.keylesspalace.tusky.entity.ScheduledStatus
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@HiltViewModel
class ScheduledStatusViewModel @Inject constructor( class ScheduledStatusViewModel @Inject constructor(
val mastodonApi: MastodonApi, val mastodonApi: MastodonApi,
val eventHub: EventHub val eventHub: EventHub

View file

@ -31,23 +31,16 @@ import com.keylesspalace.tusky.BottomSheetActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.components.search.adapter.SearchPagerAdapter import com.keylesspalace.tusky.components.search.adapter.SearchPagerAdapter
import com.keylesspalace.tusky.databinding.ActivitySearchBinding import com.keylesspalace.tusky.databinding.ActivitySearchBinding
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.reduceSwipeSensitivity import com.keylesspalace.tusky.util.reduceSwipeSensitivity
import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.unsafeLazy
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import dagger.android.DispatchingAndroidInjector import dagger.hilt.android.AndroidEntryPoint
import dagger.android.HasAndroidInjector
import javax.inject.Inject
class SearchActivity : BottomSheetActivity(), HasAndroidInjector, MenuProvider, SearchView.OnQueryTextListener { @AndroidEntryPoint
@Inject class SearchActivity : BottomSheetActivity(), MenuProvider, SearchView.OnQueryTextListener {
lateinit var androidInjector: DispatchingAndroidInjector<Any>
@Inject private val viewModel: SearchViewModel by viewModels()
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: SearchViewModel by viewModels { viewModelFactory }
private val binding by viewBinding(ActivitySearchBinding::inflate) private val binding by viewBinding(ActivitySearchBinding::inflate)
@ -167,8 +160,6 @@ class SearchActivity : BottomSheetActivity(), HasAndroidInjector, MenuProvider,
return false return false
} }
override fun androidInjector() = androidInjector
companion object { companion object {
const val TAG = "SearchActivity" const val TAG = "SearchActivity"
fun getIntent(context: Context) = Intent(context, SearchActivity::class.java) fun getIntent(context: Context) = Intent(context, SearchActivity::class.java)

View file

@ -36,11 +36,13 @@ import com.keylesspalace.tusky.usecase.TimelineCases
import com.keylesspalace.tusky.util.toViewData import com.keylesspalace.tusky.util.toViewData
import com.keylesspalace.tusky.viewdata.StatusViewData import com.keylesspalace.tusky.viewdata.StatusViewData
import com.keylesspalace.tusky.viewdata.TranslationViewData import com.keylesspalace.tusky.viewdata.TranslationViewData
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.Deferred import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@HiltViewModel
class SearchViewModel @Inject constructor( class SearchViewModel @Inject constructor(
mastodonApi: MastodonApi, mastodonApi: MastodonApi,
private val timelineCases: TimelineCases, private val timelineCases: TimelineCases,

View file

@ -24,8 +24,10 @@ import androidx.recyclerview.widget.DividerItemDecoration
import com.keylesspalace.tusky.components.search.adapter.SearchAccountsAdapter import com.keylesspalace.tusky.components.search.adapter.SearchAccountsAdapter
import com.keylesspalace.tusky.entity.TimelineAccount import com.keylesspalace.tusky.entity.TimelineAccount
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@AndroidEntryPoint
class SearchAccountsFragment : SearchFragment<TimelineAccount>() { class SearchAccountsFragment : SearchFragment<TimelineAccount>() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)

View file

@ -24,8 +24,6 @@ import com.keylesspalace.tusky.StatusListActivity
import com.keylesspalace.tusky.components.account.AccountActivity import com.keylesspalace.tusky.components.account.AccountActivity
import com.keylesspalace.tusky.components.search.SearchViewModel import com.keylesspalace.tusky.components.search.SearchViewModel
import com.keylesspalace.tusky.databinding.FragmentSearchBinding import com.keylesspalace.tusky.databinding.FragmentSearchBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.interfaces.LinkListener import com.keylesspalace.tusky.interfaces.LinkListener
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation
@ -43,17 +41,13 @@ import kotlinx.coroutines.launch
abstract class SearchFragment<T : Any> : abstract class SearchFragment<T : Any> :
Fragment(R.layout.fragment_search), Fragment(R.layout.fragment_search),
LinkListener, LinkListener,
Injectable,
SwipeRefreshLayout.OnRefreshListener, SwipeRefreshLayout.OnRefreshListener,
MenuProvider { MenuProvider {
@Inject
lateinit var viewModelFactory: ViewModelFactory
@Inject @Inject
lateinit var mastodonApi: MastodonApi lateinit var mastodonApi: MastodonApi
protected val viewModel: SearchViewModel by activityViewModels { viewModelFactory } protected val viewModel: SearchViewModel by activityViewModels()
protected val binding by viewBinding(FragmentSearchBinding::bind) protected val binding by viewBinding(FragmentSearchBinding::bind)

View file

@ -22,8 +22,10 @@ import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import com.keylesspalace.tusky.components.search.adapter.SearchHashtagsAdapter import com.keylesspalace.tusky.components.search.adapter.SearchHashtagsAdapter
import com.keylesspalace.tusky.entity.HashTag import com.keylesspalace.tusky.entity.HashTag
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@AndroidEntryPoint
class SearchHashtagsFragment : SearchFragment<HashTag>() { class SearchHashtagsFragment : SearchFragment<HashTag>() {
override val data: Flow<PagingData<HashTag>> override val data: Flow<PagingData<HashTag>>

View file

@ -65,11 +65,13 @@ import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation
import com.keylesspalace.tusky.view.showMuteAccountDialog import com.keylesspalace.tusky.view.showMuteAccountDialog
import com.keylesspalace.tusky.viewdata.AttachmentViewData import com.keylesspalace.tusky.viewdata.AttachmentViewData
import com.keylesspalace.tusky.viewdata.StatusViewData import com.keylesspalace.tusky.viewdata.StatusViewData
import dagger.hilt.android.AndroidEntryPoint
import java.util.Locale import java.util.Locale
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class SearchStatusesFragment : SearchFragment<StatusViewData.Concrete>(), StatusActionListener { class SearchStatusesFragment : SearchFragment<StatusViewData.Concrete>(), StatusActionListener {
@Inject @Inject
lateinit var accountManager: AccountManager lateinit var accountManager: AccountManager

View file

@ -14,6 +14,7 @@ import com.keylesspalace.tusky.entity.Notification
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.HttpHeaderLink import com.keylesspalace.tusky.util.HttpHeaderLink
import com.keylesspalace.tusky.util.isLessThan import com.keylesspalace.tusky.util.isLessThan
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.min import kotlin.math.min
import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.milliseconds
@ -48,7 +49,7 @@ data class Links(val next: String?, val prev: String?) {
class NotificationFetcher @Inject constructor( class NotificationFetcher @Inject constructor(
private val mastodonApi: MastodonApi, private val mastodonApi: MastodonApi,
private val accountManager: AccountManager, private val accountManager: AccountManager,
private val context: Context, @ApplicationContext private val context: Context,
private val eventHub: EventHub private val eventHub: EventHub
) { ) {
suspend fun fetchAndShow() { suspend fun fetchAndShow() {

View file

@ -52,8 +52,6 @@ import com.keylesspalace.tusky.components.timeline.viewmodel.CachedTimelineViewM
import com.keylesspalace.tusky.components.timeline.viewmodel.NetworkTimelineViewModel import com.keylesspalace.tusky.components.timeline.viewmodel.NetworkTimelineViewModel
import com.keylesspalace.tusky.components.timeline.viewmodel.TimelineViewModel import com.keylesspalace.tusky.components.timeline.viewmodel.TimelineViewModel
import com.keylesspalace.tusky.databinding.FragmentTimelineBinding import com.keylesspalace.tusky.databinding.FragmentTimelineBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.fragment.SFragment import com.keylesspalace.tusky.fragment.SFragment
import com.keylesspalace.tusky.interfaces.ActionButtonActivity import com.keylesspalace.tusky.interfaces.ActionButtonActivity
@ -77,30 +75,29 @@ import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.sizeDp
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class TimelineFragment : class TimelineFragment :
SFragment(), SFragment(),
OnRefreshListener, OnRefreshListener,
StatusActionListener, StatusActionListener,
Injectable,
ReselectableFragment, ReselectableFragment,
RefreshableFragment, RefreshableFragment,
MenuProvider { MenuProvider {
@Inject
lateinit var viewModelFactory: ViewModelFactory
@Inject @Inject
lateinit var eventHub: EventHub lateinit var eventHub: EventHub
private val viewModel: TimelineViewModel by unsafeLazy { private val viewModel: TimelineViewModel by unsafeLazy {
val viewModelProvider = ViewModelProvider(viewModelStore, defaultViewModelProviderFactory, defaultViewModelCreationExtras)
if (kind == TimelineViewModel.Kind.HOME) { if (kind == TimelineViewModel.Kind.HOME) {
ViewModelProvider(this, viewModelFactory)[CachedTimelineViewModel::class.java] viewModelProvider[CachedTimelineViewModel::class.java]
} else { } else {
ViewModelProvider(this, viewModelFactory)[NetworkTimelineViewModel::class.java] viewModelProvider[NetworkTimelineViewModel::class.java]
} }
} }

View file

@ -48,6 +48,7 @@ import com.keylesspalace.tusky.usecase.TimelineCases
import com.keylesspalace.tusky.util.EmptyPagingSource import com.keylesspalace.tusky.util.EmptyPagingSource
import com.keylesspalace.tusky.viewdata.StatusViewData import com.keylesspalace.tusky.viewdata.StatusViewData
import com.keylesspalace.tusky.viewdata.TranslationViewData import com.keylesspalace.tusky.viewdata.TranslationViewData
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -59,6 +60,7 @@ import retrofit2.HttpException
/** /**
* TimelineViewModel that caches all statuses in a local database * TimelineViewModel that caches all statuses in a local database
*/ */
@HiltViewModel
class CachedTimelineViewModel @Inject constructor( class CachedTimelineViewModel @Inject constructor(
timelineCases: TimelineCases, timelineCases: TimelineCases,
private val api: MastodonApi, private val api: MastodonApi,

View file

@ -48,6 +48,7 @@ import com.keylesspalace.tusky.util.isLessThanOrEqual
import com.keylesspalace.tusky.util.toViewData import com.keylesspalace.tusky.util.toViewData
import com.keylesspalace.tusky.viewdata.StatusViewData import com.keylesspalace.tusky.viewdata.StatusViewData
import com.keylesspalace.tusky.viewdata.TranslationViewData import com.keylesspalace.tusky.viewdata.TranslationViewData
import dagger.hilt.android.lifecycle.HiltViewModel
import java.io.IOException import java.io.IOException
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -61,6 +62,7 @@ import retrofit2.Response
/** /**
* TimelineViewModel that caches all statuses in an in-memory list * TimelineViewModel that caches all statuses in an in-memory list
*/ */
@HiltViewModel
class NetworkTimelineViewModel @Inject constructor( class NetworkTimelineViewModel @Inject constructor(
timelineCases: TimelineCases, timelineCases: TimelineCases,
private val api: MastodonApi, private val api: MastodonApi,

View file

@ -23,14 +23,10 @@ import com.keylesspalace.tusky.BaseActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.ActivityTrendingBinding import com.keylesspalace.tusky.databinding.ActivityTrendingBinding
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import dagger.android.DispatchingAndroidInjector import dagger.hilt.android.AndroidEntryPoint
import dagger.android.HasAndroidInjector
import javax.inject.Inject
class TrendingActivity : BaseActivity(), HasAndroidInjector { @AndroidEntryPoint
class TrendingActivity : BaseActivity() {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
private val binding: ActivityTrendingBinding by viewBinding(ActivityTrendingBinding::inflate) private val binding: ActivityTrendingBinding by viewBinding(ActivityTrendingBinding::inflate)
@ -54,8 +50,6 @@ class TrendingActivity : BaseActivity(), HasAndroidInjector {
} }
} }
override fun androidInjector() = dispatchingAndroidInjector
companion object { companion object {
fun getIntent(context: Context) = Intent(context, TrendingActivity::class.java) fun getIntent(context: Context) = Intent(context, TrendingActivity::class.java)
} }

View file

@ -34,8 +34,6 @@ import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.StatusListActivity import com.keylesspalace.tusky.StatusListActivity
import com.keylesspalace.tusky.components.trending.viewmodel.TrendingTagsViewModel import com.keylesspalace.tusky.components.trending.viewmodel.TrendingTagsViewModel
import com.keylesspalace.tusky.databinding.FragmentTrendingTagsBinding import com.keylesspalace.tusky.databinding.FragmentTrendingTagsBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.interfaces.ActionButtonActivity import com.keylesspalace.tusky.interfaces.ActionButtonActivity
import com.keylesspalace.tusky.interfaces.RefreshableFragment import com.keylesspalace.tusky.interfaces.RefreshableFragment
import com.keylesspalace.tusky.interfaces.ReselectableFragment import com.keylesspalace.tusky.interfaces.ReselectableFragment
@ -44,21 +42,18 @@ import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation import com.keylesspalace.tusky.util.startActivityWithSlideInAnimation
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.viewdata.TrendingViewData import com.keylesspalace.tusky.viewdata.TrendingViewData
import javax.inject.Inject import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class TrendingTagsFragment : class TrendingTagsFragment :
Fragment(R.layout.fragment_trending_tags), Fragment(R.layout.fragment_trending_tags),
OnRefreshListener, OnRefreshListener,
Injectable,
ReselectableFragment, ReselectableFragment,
RefreshableFragment { RefreshableFragment {
@Inject private val viewModel: TrendingTagsViewModel by viewModels()
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: TrendingTagsViewModel by viewModels { viewModelFactory }
private val binding by viewBinding(FragmentTrendingTagsBinding::bind) private val binding by viewBinding(FragmentTrendingTagsBinding::bind)

View file

@ -27,6 +27,7 @@ import com.keylesspalace.tusky.entity.start
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.toViewData import com.keylesspalace.tusky.util.toViewData
import com.keylesspalace.tusky.viewdata.TrendingViewData import com.keylesspalace.tusky.viewdata.TrendingViewData
import dagger.hilt.android.lifecycle.HiltViewModel
import java.io.IOException import java.io.IOException
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.async import kotlinx.coroutines.async
@ -35,6 +36,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@HiltViewModel
class TrendingTagsViewModel @Inject constructor( class TrendingTagsViewModel @Inject constructor(
private val mastodonApi: MastodonApi, private val mastodonApi: MastodonApi,
private val eventHub: EventHub private val eventHub: EventHub

View file

@ -23,17 +23,13 @@ import com.keylesspalace.tusky.BottomSheetActivity
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.ActivityViewThreadBinding import com.keylesspalace.tusky.databinding.ActivityViewThreadBinding
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import dagger.android.DispatchingAndroidInjector import dagger.hilt.android.AndroidEntryPoint
import dagger.android.HasAndroidInjector
import javax.inject.Inject
class ViewThreadActivity : BottomSheetActivity(), HasAndroidInjector { @AndroidEntryPoint
class ViewThreadActivity : BottomSheetActivity() {
private val binding by viewBinding(ActivityViewThreadBinding::inflate) private val binding by viewBinding(ActivityViewThreadBinding::inflate)
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(binding.root) setContentView(binding.root)
@ -54,8 +50,6 @@ class ViewThreadActivity : BottomSheetActivity(), HasAndroidInjector {
} }
} }
override fun androidInjector() = dispatchingAndroidInjector
companion object { companion object {
fun startIntent(context: Context, id: String, url: String): Intent { fun startIntent(context: Context, id: String, url: String): Intent {

View file

@ -42,8 +42,6 @@ import com.keylesspalace.tusky.components.accountlist.AccountListActivity
import com.keylesspalace.tusky.components.accountlist.AccountListActivity.Companion.newIntent import com.keylesspalace.tusky.components.accountlist.AccountListActivity.Companion.newIntent
import com.keylesspalace.tusky.components.viewthread.edits.ViewEditsFragment import com.keylesspalace.tusky.components.viewthread.edits.ViewEditsFragment
import com.keylesspalace.tusky.databinding.FragmentViewThreadBinding import com.keylesspalace.tusky.databinding.FragmentViewThreadBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.fragment.SFragment import com.keylesspalace.tusky.fragment.SFragment
import com.keylesspalace.tusky.interfaces.StatusActionListener import com.keylesspalace.tusky.interfaces.StatusActionListener
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
@ -58,23 +56,20 @@ import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.viewdata.AttachmentViewData.Companion.list import com.keylesspalace.tusky.viewdata.AttachmentViewData.Companion.list
import com.keylesspalace.tusky.viewdata.StatusViewData import com.keylesspalace.tusky.viewdata.StatusViewData
import com.keylesspalace.tusky.viewdata.TranslationViewData import com.keylesspalace.tusky.viewdata.TranslationViewData
import javax.inject.Inject import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class ViewThreadFragment : class ViewThreadFragment :
SFragment(), SFragment(),
OnRefreshListener, OnRefreshListener,
StatusActionListener, StatusActionListener,
MenuProvider, MenuProvider {
Injectable {
@Inject private val viewModel: ViewThreadViewModel by viewModels()
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: ViewThreadViewModel by viewModels { viewModelFactory }
private val binding by viewBinding(FragmentViewThreadBinding::bind) private val binding by viewBinding(FragmentViewThreadBinding::bind)

View file

@ -45,6 +45,7 @@ import com.keylesspalace.tusky.util.toViewData
import com.keylesspalace.tusky.viewdata.StatusViewData import com.keylesspalace.tusky.viewdata.StatusViewData
import com.keylesspalace.tusky.viewdata.TranslationViewData import com.keylesspalace.tusky.viewdata.TranslationViewData
import com.squareup.moshi.Moshi import com.squareup.moshi.Moshi
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.async import kotlinx.coroutines.async
@ -58,6 +59,7 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@HiltViewModel
class ViewThreadViewModel @Inject constructor( class ViewThreadViewModel @Inject constructor(
private val api: MastodonApi, private val api: MastodonApi,
private val filterModel: FilterModel, private val filterModel: FilterModel,

View file

@ -38,8 +38,6 @@ import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.StatusListActivity import com.keylesspalace.tusky.StatusListActivity
import com.keylesspalace.tusky.components.account.AccountActivity import com.keylesspalace.tusky.components.account.AccountActivity
import com.keylesspalace.tusky.databinding.FragmentViewEditsBinding import com.keylesspalace.tusky.databinding.FragmentViewEditsBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.interfaces.LinkListener import com.keylesspalace.tusky.interfaces.LinkListener
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
import com.keylesspalace.tusky.util.emojify import com.keylesspalace.tusky.util.emojify
@ -53,20 +51,17 @@ import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp import com.mikepenz.iconics.utils.sizeDp
import javax.inject.Inject import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@AndroidEntryPoint
class ViewEditsFragment : class ViewEditsFragment :
Fragment(R.layout.fragment_view_edits), Fragment(R.layout.fragment_view_edits),
LinkListener, LinkListener,
OnRefreshListener, OnRefreshListener,
MenuProvider, MenuProvider {
Injectable {
@Inject private val viewModel: ViewEditsViewModel by viewModels()
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: ViewEditsViewModel by viewModels { viewModelFactory }
private val binding by viewBinding(FragmentViewEditsBinding::bind) private val binding by viewBinding(FragmentViewEditsBinding::bind)

View file

@ -22,6 +22,7 @@ import com.keylesspalace.tusky.components.viewthread.edits.EditsTagHandler.Compa
import com.keylesspalace.tusky.components.viewthread.edits.EditsTagHandler.Companion.INSERTED_TEXT_EL import com.keylesspalace.tusky.components.viewthread.edits.EditsTagHandler.Companion.INSERTED_TEXT_EL
import com.keylesspalace.tusky.entity.StatusEdit import com.keylesspalace.tusky.entity.StatusEdit
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -43,13 +44,14 @@ import org.pageseeder.diffx.xml.NamespaceSet
import org.pageseeder.xmlwriter.XML.NamespaceAware import org.pageseeder.xmlwriter.XML.NamespaceAware
import org.pageseeder.xmlwriter.XMLStringWriter import org.pageseeder.xmlwriter.XMLStringWriter
@HiltViewModel
class ViewEditsViewModel @Inject constructor(private val api: MastodonApi) : ViewModel() { class ViewEditsViewModel @Inject constructor(private val api: MastodonApi) : ViewModel() {
private val _uiState = MutableStateFlow(EditsUiState.Initial as EditsUiState) private val _uiState = MutableStateFlow(EditsUiState.Initial as EditsUiState)
val uiState: StateFlow<EditsUiState> = _uiState.asStateFlow() val uiState: StateFlow<EditsUiState> = _uiState.asStateFlow()
/** The API call to fetch edit history returned less than two items */ /** The API call to fetch edit history returned less than two items */
object MissingEditsException : Exception() class MissingEditsException : Exception()
fun loadEdits(statusId: String, force: Boolean = false, refreshing: Boolean = false) { fun loadEdits(statusId: String, force: Boolean = false, refreshing: Boolean = false) {
if (!force && _uiState.value !is EditsUiState.Initial) return if (!force && _uiState.value !is EditsUiState.Initial) return
@ -69,7 +71,7 @@ class ViewEditsViewModel @Inject constructor(private val api: MastodonApi) : Vie
// `edits` might have fewer than the minimum number of entries because of // `edits` might have fewer than the minimum number of entries because of
// https://github.com/mastodon/mastodon/issues/25398. // https://github.com/mastodon/mastodon/issues/25398.
if (edits.size < 2) { if (edits.size < 2) {
_uiState.value = EditsUiState.Error(MissingEditsException) _uiState.value = EditsUiState.Error(MissingEditsException())
return@launch return@launch
} }

View file

@ -1,135 +0,0 @@
/* Copyright 2018 charlag
*
* 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 com.keylesspalace.tusky.AboutActivity
import com.keylesspalace.tusky.BaseActivity
import com.keylesspalace.tusky.EditProfileActivity
import com.keylesspalace.tusky.LicenseActivity
import com.keylesspalace.tusky.ListsActivity
import com.keylesspalace.tusky.MainActivity
import com.keylesspalace.tusky.SplashActivity
import com.keylesspalace.tusky.StatusListActivity
import com.keylesspalace.tusky.TabPreferenceActivity
import com.keylesspalace.tusky.ViewMediaActivity
import com.keylesspalace.tusky.components.account.AccountActivity
import com.keylesspalace.tusky.components.accountlist.AccountListActivity
import com.keylesspalace.tusky.components.announcements.AnnouncementsActivity
import com.keylesspalace.tusky.components.compose.ComposeActivity
import com.keylesspalace.tusky.components.domainblocks.DomainBlocksActivity
import com.keylesspalace.tusky.components.drafts.DraftsActivity
import com.keylesspalace.tusky.components.filters.EditFilterActivity
import com.keylesspalace.tusky.components.filters.FiltersActivity
import com.keylesspalace.tusky.components.followedtags.FollowedTagsActivity
import com.keylesspalace.tusky.components.login.LoginActivity
import com.keylesspalace.tusky.components.login.LoginWebViewActivity
import com.keylesspalace.tusky.components.preference.PreferencesActivity
import com.keylesspalace.tusky.components.report.ReportActivity
import com.keylesspalace.tusky.components.scheduled.ScheduledStatusActivity
import com.keylesspalace.tusky.components.search.SearchActivity
import com.keylesspalace.tusky.components.trending.TrendingActivity
import com.keylesspalace.tusky.components.viewthread.ViewThreadActivity
import dagger.Module
import dagger.android.ContributesAndroidInjector
/**
* Created by charlag on 3/24/18.
*/
@Module
abstract class ActivitiesModule {
@ContributesAndroidInjector
abstract fun contributesBaseActivity(): BaseActivity
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesMainActivity(): MainActivity
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesAccountActivity(): AccountActivity
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesListsActivity(): ListsActivity
@ContributesAndroidInjector
abstract fun contributesComposeActivity(): ComposeActivity
@ContributesAndroidInjector
abstract fun contributesEditProfileActivity(): EditProfileActivity
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesAccountListActivity(): AccountListActivity
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesViewThreadActivity(): ViewThreadActivity
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesStatusListActivity(): StatusListActivity
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesSearchActivity(): SearchActivity
@ContributesAndroidInjector
abstract fun contributesAboutActivity(): AboutActivity
@ContributesAndroidInjector
abstract fun contributesLoginActivity(): LoginActivity
@ContributesAndroidInjector
abstract fun contributesLoginWebViewActivity(): LoginWebViewActivity
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesPreferencesActivity(): PreferencesActivity
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesViewMediaActivity(): ViewMediaActivity
@ContributesAndroidInjector
abstract fun contributesLicenseActivity(): LicenseActivity
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesTabPreferenceActivity(): TabPreferenceActivity
@ContributesAndroidInjector
abstract fun contributesFiltersActivity(): FiltersActivity
@ContributesAndroidInjector
abstract fun contributesFollowedTagsActivity(): FollowedTagsActivity
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesReportActivity(): ReportActivity
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesInstanceListActivity(): DomainBlocksActivity
@ContributesAndroidInjector
abstract fun contributesScheduledStatusActivity(): ScheduledStatusActivity
@ContributesAndroidInjector
abstract fun contributesAnnouncementsActivity(): AnnouncementsActivity
@ContributesAndroidInjector
abstract fun contributesDraftActivity(): DraftsActivity
@ContributesAndroidInjector
abstract fun contributesSplashActivity(): SplashActivity
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesTrendingActivity(): TrendingActivity
@ContributesAndroidInjector
abstract fun contributesEditFilterActivity(): EditFilterActivity
}

View file

@ -1,53 +0,0 @@
/* Copyright 2018 charlag
*
* 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 com.keylesspalace.tusky.TuskyApplication
import dagger.BindsInstance
import dagger.Component
import dagger.android.support.AndroidSupportInjectionModule
import javax.inject.Singleton
/**
* Created by charlag on 3/21/18.
*/
@Singleton
@Component(
modules = [
AppModule::class,
CoroutineScopeModule::class,
NetworkModule::class,
AndroidSupportInjectionModule::class,
ActivitiesModule::class,
ServicesModule::class,
BroadcastReceiverModule::class,
ViewModelModule::class,
WorkerModule::class,
PlayerModule::class
]
)
interface AppComponent {
@Component.Builder
interface Builder {
@BindsInstance
fun application(tuskyApp: TuskyApplication): Builder
fun build(): AppComponent
}
fun inject(app: TuskyApplication)
}

View file

@ -1,85 +0,0 @@
/* Copyright 2018 charlag
*
* 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.app.Activity
import android.app.Application
import android.content.Context
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import com.keylesspalace.tusky.TuskyApplication
import dagger.android.AndroidInjection
import dagger.android.HasAndroidInjector
import dagger.android.support.AndroidSupportInjection
/**
* Created by charlag on 3/24/18.
*/
object AppInjector {
fun init(app: TuskyApplication) {
DaggerAppComponent.builder().application(app)
.build().inject(app)
app.registerActivityLifecycleCallbacks(object : Application.ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
handleActivity(activity)
}
override fun onActivityPaused(activity: Activity) {
}
override fun onActivityResumed(activity: Activity) {
}
override fun onActivityStarted(activity: Activity) {
}
override fun onActivityDestroyed(activity: Activity) {
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
}
override fun onActivityStopped(activity: Activity) {
}
})
}
private fun handleActivity(activity: Activity) {
if (activity is HasAndroidInjector || activity is Injectable) {
AndroidInjection.inject(activity)
}
if (activity is FragmentActivity) {
activity.supportFragmentManager.registerFragmentLifecycleCallbacks(
object : FragmentManager.FragmentLifecycleCallbacks() {
override fun onFragmentPreAttached(
fm: FragmentManager,
f: Fragment,
context: Context
) {
if (f is Injectable) {
AndroidSupportInjection.inject(f)
}
}
},
true
)
}
}
}

View file

@ -1,35 +0,0 @@
/* Copyright 2018 Jeremiasz Nelz <remi6397(a)gmail.com>
* Copyright 2018 Conny Duck
*
* 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 com.keylesspalace.tusky.receiver.NotificationBlockStateBroadcastReceiver
import com.keylesspalace.tusky.receiver.SendStatusBroadcastReceiver
import com.keylesspalace.tusky.receiver.UnifiedPushBroadcastReceiver
import dagger.Module
import dagger.android.ContributesAndroidInjector
@Module
abstract class BroadcastReceiverModule {
@ContributesAndroidInjector
abstract fun contributeSendStatusBroadcastReceiver(): SendStatusBroadcastReceiver
@ContributesAndroidInjector
abstract fun contributeUnifiedPushBroadcastReceiver(): UnifiedPushBroadcastReceiver
@ContributesAndroidInjector
abstract fun contributeNotificationBlockStateBroadcastReceiver(): NotificationBlockStateBroadcastReceiver
}

View file

@ -19,6 +19,8 @@ package com.keylesspalace.tusky.di
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Qualifier import javax.inject.Qualifier
import javax.inject.Singleton import javax.inject.Singleton
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -38,7 +40,8 @@ import kotlinx.coroutines.SupervisorJob
annotation class ApplicationScope annotation class ApplicationScope
@Module @Module
class CoroutineScopeModule { @InstallIn(SingletonComponent::class)
object CoroutineScopeModule {
@ApplicationScope @ApplicationScope
@Provides @Provides
@Singleton @Singleton

View file

@ -1,110 +0,0 @@
/* Copyright 2018 charlag
*
* 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 com.keylesspalace.tusky.AccountsInListFragment
import com.keylesspalace.tusky.components.account.list.ListSelectionFragment
import com.keylesspalace.tusky.components.account.media.AccountMediaFragment
import com.keylesspalace.tusky.components.accountlist.AccountListFragment
import com.keylesspalace.tusky.components.conversation.ConversationsFragment
import com.keylesspalace.tusky.components.domainblocks.DomainBlocksFragment
import com.keylesspalace.tusky.components.notifications.NotificationsFragment
import com.keylesspalace.tusky.components.preference.AccountPreferencesFragment
import com.keylesspalace.tusky.components.preference.NotificationPreferencesFragment
import com.keylesspalace.tusky.components.preference.PreferencesFragment
import com.keylesspalace.tusky.components.preference.TabFilterPreferencesFragment
import com.keylesspalace.tusky.components.report.fragments.ReportDoneFragment
import com.keylesspalace.tusky.components.report.fragments.ReportNoteFragment
import com.keylesspalace.tusky.components.report.fragments.ReportStatusesFragment
import com.keylesspalace.tusky.components.search.fragments.SearchAccountsFragment
import com.keylesspalace.tusky.components.search.fragments.SearchHashtagsFragment
import com.keylesspalace.tusky.components.search.fragments.SearchStatusesFragment
import com.keylesspalace.tusky.components.timeline.TimelineFragment
import com.keylesspalace.tusky.components.trending.TrendingTagsFragment
import com.keylesspalace.tusky.components.viewthread.ViewThreadFragment
import com.keylesspalace.tusky.components.viewthread.edits.ViewEditsFragment
import com.keylesspalace.tusky.fragment.ViewVideoFragment
import dagger.Module
import dagger.android.ContributesAndroidInjector
@Module
abstract class FragmentBuildersModule {
@ContributesAndroidInjector
abstract fun accountListFragment(): AccountListFragment
@ContributesAndroidInjector
abstract fun accountMediaFragment(): AccountMediaFragment
@ContributesAndroidInjector
abstract fun viewThreadFragment(): ViewThreadFragment
@ContributesAndroidInjector
abstract fun viewEditsFragment(): ViewEditsFragment
@ContributesAndroidInjector
abstract fun timelineFragment(): TimelineFragment
@ContributesAndroidInjector
abstract fun notificationsFragment(): NotificationsFragment
@ContributesAndroidInjector
abstract fun notificationPreferencesFragment(): NotificationPreferencesFragment
@ContributesAndroidInjector
abstract fun accountPreferencesFragment(): AccountPreferencesFragment
@ContributesAndroidInjector
abstract fun conversationsFragment(): ConversationsFragment
@ContributesAndroidInjector
abstract fun accountInListsFragment(): AccountsInListFragment
@ContributesAndroidInjector
abstract fun reportStatusesFragment(): ReportStatusesFragment
@ContributesAndroidInjector
abstract fun reportNoteFragment(): ReportNoteFragment
@ContributesAndroidInjector
abstract fun reportDoneFragment(): ReportDoneFragment
@ContributesAndroidInjector
abstract fun instanceListFragment(): DomainBlocksFragment
@ContributesAndroidInjector
abstract fun searchStatusesFragment(): SearchStatusesFragment
@ContributesAndroidInjector
abstract fun searchAccountFragment(): SearchAccountsFragment
@ContributesAndroidInjector
abstract fun searchHashtagsFragment(): SearchHashtagsFragment
@ContributesAndroidInjector
abstract fun preferencesFragment(): PreferencesFragment
@ContributesAndroidInjector
abstract fun listsForAccountFragment(): ListSelectionFragment
@ContributesAndroidInjector
abstract fun trendingTagsFragment(): TrendingTagsFragment
@ContributesAndroidInjector
abstract fun viewVideoFragment(): ViewVideoFragment
@ContributesAndroidInjector
abstract fun tabFilterPreferencesFragment(): TabFilterPreferencesFragment
}

View file

@ -1,22 +0,0 @@
/* Copyright 2018 charlag
*
* 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
/**
* Created by charlag on 3/24/18.
*/
interface Injectable

View file

@ -39,6 +39,9 @@ import com.squareup.moshi.adapters.EnumJsonAdapter
import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import java.net.IDN import java.net.IDN
import java.net.InetSocketAddress import java.net.InetSocketAddress
import java.net.Proxy import java.net.Proxy
@ -58,6 +61,7 @@ import retrofit2.create
*/ */
@Module @Module
@InstallIn(SingletonComponent::class)
object NetworkModule { object NetworkModule {
private const val TAG = "NetworkModule" private const val TAG = "NetworkModule"
@ -89,7 +93,7 @@ object NetworkModule {
@Singleton @Singleton
fun providesHttpClient( fun providesHttpClient(
accountManager: AccountManager, accountManager: AccountManager,
context: Context, @ApplicationContext context: Context,
preferences: SharedPreferences preferences: SharedPreferences
): OkHttpClient { ): OkHttpClient {
val httpProxyEnabled = preferences.getBoolean(HTTP_PROXY_ENABLED, false) val httpProxyEnabled = preferences.getBoolean(HTTP_PROXY_ENABLED, false)

View file

@ -53,19 +53,26 @@ import androidx.media3.extractor.text.webvtt.WebvttParser
import androidx.media3.extractor.wav.WavExtractor import androidx.media3.extractor.wav.WavExtractor
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@Module @Module
@InstallIn(SingletonComponent::class)
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
object PlayerModule { object PlayerModule {
@Provides @Provides
fun provideAudioSink(context: Context): AudioSink { fun provideAudioSink(@ApplicationContext context: Context): AudioSink {
return DefaultAudioSink.Builder(context) return DefaultAudioSink.Builder(context)
.build() .build()
} }
@Provides @Provides
fun provideRenderersFactory(context: Context, audioSink: AudioSink): RenderersFactory { fun provideRenderersFactory(
@ApplicationContext context: Context,
audioSink: AudioSink
): RenderersFactory {
return RenderersFactory { eventHandler, return RenderersFactory { eventHandler,
videoRendererEventListener, videoRendererEventListener,
audioRendererEventListener, audioRendererEventListener,
@ -154,7 +161,10 @@ object PlayerModule {
} }
@Provides @Provides
fun provideDataSourceFactory(context: Context, okHttpClient: OkHttpClient): DataSource.Factory { fun provideDataSourceFactory(
@ApplicationContext context: Context,
okHttpClient: OkHttpClient
): DataSource.Factory {
return DefaultDataSource.Factory(context, OkHttpDataSource.Factory(okHttpClient)) return DefaultDataSource.Factory(context, OkHttpDataSource.Factory(okHttpClient))
} }
@ -169,7 +179,7 @@ object PlayerModule {
@Provides @Provides
fun provideExoPlayer( fun provideExoPlayer(
context: Context, @ApplicationContext context: Context,
renderersFactory: RenderersFactory, renderersFactory: RenderersFactory,
mediaSourceFactory: MediaSource.Factory mediaSourceFactory: MediaSource.Factory
): ExoPlayer { ): ExoPlayer {

View file

@ -1,26 +0,0 @@
/* Copyright 2018 Conny Duck
*
* 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 com.keylesspalace.tusky.service.SendStatusService
import dagger.Module
import dagger.android.ContributesAndroidInjector
@Module
abstract class ServicesModule {
@ContributesAndroidInjector
abstract fun contributesSendStatusService(): SendStatusService
}

View file

@ -15,16 +15,17 @@
package com.keylesspalace.tusky.di package com.keylesspalace.tusky.di
import android.app.Application
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.room.Room import androidx.room.Room
import com.keylesspalace.tusky.TuskyApplication
import com.keylesspalace.tusky.db.AppDatabase import com.keylesspalace.tusky.db.AppDatabase
import com.keylesspalace.tusky.db.Converters import com.keylesspalace.tusky.db.Converters
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton import javax.inject.Singleton
/** /**
@ -32,22 +33,17 @@ import javax.inject.Singleton
*/ */
@Module @Module
class AppModule { @InstallIn(SingletonComponent::class)
object StorageModule {
@Provides @Provides
fun providesApplication(app: TuskyApplication): Application = app fun providesSharedPreferences(@ApplicationContext appContext: Context): SharedPreferences {
return PreferenceManager.getDefaultSharedPreferences(appContext)
@Provides
fun providesContext(app: Application): Context = app
@Provides
fun providesSharedPreferences(app: Application): SharedPreferences {
return PreferenceManager.getDefaultSharedPreferences(app)
} }
@Provides @Provides
@Singleton @Singleton
fun providesDatabase(appContext: Context, converters: Converters): AppDatabase { fun providesDatabase(@ApplicationContext appContext: Context, converters: Converters): AppDatabase {
return Room.databaseBuilder(appContext, AppDatabase::class.java, "tuskyDB") return Room.databaseBuilder(appContext, AppDatabase::class.java, "tuskyDB")
.addTypeConverter(converters) .addTypeConverter(converters)
.allowMainThreadQueries() .allowMainThreadQueries()

View file

@ -1,202 +0,0 @@
/*
* Copyright 2023 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>.
*/
// from https://proandroiddev.com/viewmodel-with-dagger2-architecture-components-2e06f06c9455
package com.keylesspalace.tusky.di
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.keylesspalace.tusky.components.account.AccountViewModel
import com.keylesspalace.tusky.components.account.list.ListsForAccountViewModel
import com.keylesspalace.tusky.components.account.media.AccountMediaViewModel
import com.keylesspalace.tusky.components.announcements.AnnouncementsViewModel
import com.keylesspalace.tusky.components.compose.ComposeViewModel
import com.keylesspalace.tusky.components.conversation.ConversationsViewModel
import com.keylesspalace.tusky.components.domainblocks.DomainBlocksViewModel
import com.keylesspalace.tusky.components.drafts.DraftsViewModel
import com.keylesspalace.tusky.components.filters.EditFilterViewModel
import com.keylesspalace.tusky.components.filters.FiltersViewModel
import com.keylesspalace.tusky.components.followedtags.FollowedTagsViewModel
import com.keylesspalace.tusky.components.login.LoginWebViewViewModel
import com.keylesspalace.tusky.components.notifications.NotificationsViewModel
import com.keylesspalace.tusky.components.report.ReportViewModel
import com.keylesspalace.tusky.components.scheduled.ScheduledStatusViewModel
import com.keylesspalace.tusky.components.search.SearchViewModel
import com.keylesspalace.tusky.components.timeline.viewmodel.CachedTimelineViewModel
import com.keylesspalace.tusky.components.timeline.viewmodel.NetworkTimelineViewModel
import com.keylesspalace.tusky.components.trending.viewmodel.TrendingTagsViewModel
import com.keylesspalace.tusky.components.viewthread.ViewThreadViewModel
import com.keylesspalace.tusky.components.viewthread.edits.ViewEditsViewModel
import com.keylesspalace.tusky.viewmodel.AccountsInListViewModel
import com.keylesspalace.tusky.viewmodel.EditProfileViewModel
import com.keylesspalace.tusky.viewmodel.ListsViewModel
import dagger.Binds
import dagger.MapKey
import dagger.Module
import dagger.multibindings.IntoMap
import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Singleton
import kotlin.reflect.KClass
@Singleton
class ViewModelFactory @Inject constructor(
private val viewModels: MutableMap<Class<out ViewModel>, Provider<ViewModel>>
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T =
viewModels[modelClass]?.get() as T
}
@Target(
AnnotationTarget.FUNCTION,
AnnotationTarget.PROPERTY_GETTER,
AnnotationTarget.PROPERTY_SETTER
)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
@Module
abstract class ViewModelModule {
@Binds
internal abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory
@Binds
@IntoMap
@ViewModelKey(AccountViewModel::class)
internal abstract fun accountViewModel(viewModel: AccountViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(EditProfileViewModel::class)
internal abstract fun editProfileViewModel(viewModel: EditProfileViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(ConversationsViewModel::class)
internal abstract fun conversationsViewModel(viewModel: ConversationsViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(ListsViewModel::class)
internal abstract fun listsViewModel(viewModel: ListsViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(AccountsInListViewModel::class)
internal abstract fun accountsInListViewModel(viewModel: AccountsInListViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(ReportViewModel::class)
internal abstract fun reportViewModel(viewModel: ReportViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(SearchViewModel::class)
internal abstract fun searchViewModel(viewModel: SearchViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(ComposeViewModel::class)
internal abstract fun composeViewModel(viewModel: ComposeViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(ScheduledStatusViewModel::class)
internal abstract fun scheduledStatusViewModel(viewModel: ScheduledStatusViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(AnnouncementsViewModel::class)
internal abstract fun announcementsViewModel(viewModel: AnnouncementsViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(DraftsViewModel::class)
internal abstract fun draftsViewModel(viewModel: DraftsViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(CachedTimelineViewModel::class)
internal abstract fun cachedTimelineViewModel(viewModel: CachedTimelineViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(NetworkTimelineViewModel::class)
internal abstract fun networkTimelineViewModel(viewModel: NetworkTimelineViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(ViewThreadViewModel::class)
internal abstract fun viewThreadViewModel(viewModel: ViewThreadViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(ViewEditsViewModel::class)
internal abstract fun viewEditsViewModel(viewModel: ViewEditsViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(AccountMediaViewModel::class)
internal abstract fun accountMediaViewModel(viewModel: AccountMediaViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(LoginWebViewViewModel::class)
internal abstract fun loginWebViewViewModel(viewModel: LoginWebViewViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(FollowedTagsViewModel::class)
internal abstract fun followedTagsViewModel(viewModel: FollowedTagsViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(ListsForAccountViewModel::class)
internal abstract fun listsForAccountViewModel(viewModel: ListsForAccountViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(TrendingTagsViewModel::class)
internal abstract fun trendingTagsViewModel(viewModel: TrendingTagsViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(FiltersViewModel::class)
internal abstract fun filtersViewModel(viewModel: FiltersViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(EditFilterViewModel::class)
internal abstract fun editFilterViewModel(viewModel: EditFilterViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(DomainBlocksViewModel::class)
internal abstract fun instanceMuteViewModel(viewModel: DomainBlocksViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(NotificationsViewModel::class)
internal abstract fun notificationsViewModel(viewModel: NotificationsViewModel): ViewModel
// Add more ViewModels here
}

View file

@ -1,49 +0,0 @@
/*
* Copyright 2023 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 androidx.work.ListenableWorker
import com.keylesspalace.tusky.worker.ChildWorkerFactory
import com.keylesspalace.tusky.worker.NotificationWorker
import com.keylesspalace.tusky.worker.PruneCacheWorker
import dagger.Binds
import dagger.MapKey
import dagger.Module
import dagger.multibindings.IntoMap
import kotlin.reflect.KClass
@Retention(AnnotationRetention.RUNTIME)
@MapKey
annotation class WorkerKey(val value: KClass<out ListenableWorker>)
@Module
abstract class WorkerModule {
@Binds
@IntoMap
@WorkerKey(NotificationWorker::class)
internal abstract fun bindNotificationWorkerFactory(
worker: NotificationWorker.Factory
): ChildWorkerFactory
@Binds
@IntoMap
@WorkerKey(PruneCacheWorker::class)
internal abstract fun bindPruneCacheWorkerFactory(
worker: PruneCacheWorker.Factory
): ChildWorkerFactory
}

View file

@ -52,7 +52,6 @@ import com.keylesspalace.tusky.components.instanceinfo.InstanceInfoRepository
import com.keylesspalace.tusky.components.report.ReportActivity.Companion.getIntent import com.keylesspalace.tusky.components.report.ReportActivity.Companion.getIntent
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.db.entity.AccountEntity import com.keylesspalace.tusky.db.entity.AccountEntity
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.Attachment import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.entity.Translation import com.keylesspalace.tusky.entity.Translation
@ -74,7 +73,7 @@ import kotlinx.coroutines.launch
* adapters. I feel like the profile pages and thread viewer, which I haven't made yet, will also * adapters. I feel like the profile pages and thread viewer, which I haven't made yet, will also
* overlap functionality. So, I'm momentarily leaving it and hopefully working on those will clear * overlap functionality. So, I'm momentarily leaving it and hopefully working on those will clear
* up what needs to be where. */ * up what needs to be where. */
abstract class SFragment : Fragment(), Injectable { abstract class SFragment : Fragment() {
protected abstract fun removeItem(position: Int) protected abstract fun removeItem(position: Int)
protected abstract fun onReblog(reblog: Boolean, position: Int) protected abstract fun onReblog(reblog: Boolean, position: Int)

View file

@ -50,18 +50,19 @@ import com.keylesspalace.tusky.BuildConfig
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.ViewMediaActivity import com.keylesspalace.tusky.ViewMediaActivity
import com.keylesspalace.tusky.databinding.FragmentViewVideoBinding import com.keylesspalace.tusky.databinding.FragmentViewVideoBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.Attachment import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.util.getParcelableCompat import com.keylesspalace.tusky.util.getParcelableCompat
import com.keylesspalace.tusky.util.hide import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.viewBinding import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible import com.keylesspalace.tusky.util.visible
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Provider import javax.inject.Provider
import kotlin.math.abs import kotlin.math.abs
@AndroidEntryPoint
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
class ViewVideoFragment : ViewMediaFragment(), Injectable { class ViewVideoFragment : ViewMediaFragment() {
interface VideoActionsListener { interface VideoActionsListener {
fun onDismiss() fun onDismiss()
} }

View file

@ -26,13 +26,12 @@ import com.keylesspalace.tusky.components.systemnotifications.updateUnifiedPushS
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.ApplicationScope import com.keylesspalace.tusky.di.ApplicationScope
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import dagger.android.AndroidInjection import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@DelicateCoroutinesApi @AndroidEntryPoint
class NotificationBlockStateBroadcastReceiver : BroadcastReceiver() { class NotificationBlockStateBroadcastReceiver : BroadcastReceiver() {
@Inject @Inject
lateinit var mastodonApi: MastodonApi lateinit var mastodonApi: MastodonApi
@ -45,7 +44,6 @@ class NotificationBlockStateBroadcastReceiver : BroadcastReceiver() {
lateinit var externalScope: CoroutineScope lateinit var externalScope: CoroutineScope
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
AndroidInjection.inject(this, context)
if (Build.VERSION.SDK_INT < 28) return if (Build.VERSION.SDK_INT < 28) return
if (!canEnablePushNotifications(context, accountManager)) return if (!canEnablePushNotifications(context, accountManager)) return

View file

@ -31,11 +31,12 @@ import com.keylesspalace.tusky.service.SendStatusService
import com.keylesspalace.tusky.service.StatusToSend import com.keylesspalace.tusky.service.StatusToSend
import com.keylesspalace.tusky.util.getSerializableExtraCompat import com.keylesspalace.tusky.util.getSerializableExtraCompat
import com.keylesspalace.tusky.util.randomAlphanumericString import com.keylesspalace.tusky.util.randomAlphanumericString
import dagger.android.AndroidInjection import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
private const val TAG = "SendStatusBR" private const val TAG = "SendStatusBR"
@AndroidEntryPoint
class SendStatusBroadcastReceiver : BroadcastReceiver() { class SendStatusBroadcastReceiver : BroadcastReceiver() {
@Inject @Inject
@ -43,8 +44,6 @@ class SendStatusBroadcastReceiver : BroadcastReceiver() {
@SuppressLint("MissingPermission") @SuppressLint("MissingPermission")
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
AndroidInjection.inject(this, context)
if (intent.action == NotificationHelper.REPLY_ACTION) { if (intent.action == NotificationHelper.REPLY_ACTION) {
val serverNotificationId = intent.getStringExtra(NotificationHelper.KEY_SERVER_NOTIFICATION_ID) val serverNotificationId = intent.getStringExtra(NotificationHelper.KEY_SERVER_NOTIFICATION_ID)
val senderId = intent.getLongExtra(NotificationHelper.KEY_SENDER_ACCOUNT_ID, -1) val senderId = intent.getLongExtra(NotificationHelper.KEY_SENDER_ACCOUNT_ID, -1)

View file

@ -16,7 +16,6 @@
package com.keylesspalace.tusky.receiver package com.keylesspalace.tusky.receiver
import android.content.Context import android.content.Context
import android.content.Intent
import android.util.Log import android.util.Log
import androidx.work.OneTimeWorkRequest import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager import androidx.work.WorkManager
@ -26,14 +25,13 @@ import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.ApplicationScope import com.keylesspalace.tusky.di.ApplicationScope
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.worker.NotificationWorker import com.keylesspalace.tusky.worker.NotificationWorker
import dagger.android.AndroidInjection import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.unifiedpush.android.connector.MessagingReceiver import org.unifiedpush.android.connector.MessagingReceiver
@DelicateCoroutinesApi @AndroidEntryPoint
class UnifiedPushBroadcastReceiver : MessagingReceiver() { class UnifiedPushBroadcastReceiver : MessagingReceiver() {
companion object { companion object {
const val TAG = "UnifiedPush" const val TAG = "UnifiedPush"
@ -49,13 +47,7 @@ class UnifiedPushBroadcastReceiver : MessagingReceiver() {
@ApplicationScope @ApplicationScope
lateinit var externalScope: CoroutineScope lateinit var externalScope: CoroutineScope
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
AndroidInjection.inject(this, context)
}
override fun onMessage(context: Context, message: ByteArray, instance: String) { override fun onMessage(context: Context, message: ByteArray, instance: String) {
AndroidInjection.inject(this, context)
Log.d(TAG, "New message received for account $instance") Log.d(TAG, "New message received for account $instance")
val workManager = WorkManager.getInstance(context) val workManager = WorkManager.getInstance(context)
val request = OneTimeWorkRequest.from(NotificationWorker::class.java) val request = OneTimeWorkRequest.from(NotificationWorker::class.java)
@ -63,7 +55,6 @@ class UnifiedPushBroadcastReceiver : MessagingReceiver() {
} }
override fun onNewEndpoint(context: Context, endpoint: String, instance: String) { override fun onNewEndpoint(context: Context, endpoint: String, instance: String) {
AndroidInjection.inject(this, context)
Log.d(TAG, "Endpoint available for account $instance: $endpoint") Log.d(TAG, "Endpoint available for account $instance: $endpoint")
accountManager.getAccountById(instance.toLong())?.let { accountManager.getAccountById(instance.toLong())?.let {
externalScope.launch { externalScope.launch {
@ -75,7 +66,6 @@ class UnifiedPushBroadcastReceiver : MessagingReceiver() {
override fun onRegistrationFailed(context: Context, instance: String) = Unit override fun onRegistrationFailed(context: Context, instance: String) = Unit
override fun onUnregistered(context: Context, instance: String) { override fun onUnregistered(context: Context, instance: String) {
AndroidInjection.inject(this, context)
Log.d(TAG, "Endpoint unregistered for account $instance") Log.d(TAG, "Endpoint unregistered for account $instance")
accountManager.getAccountById(instance.toLong())?.let { accountManager.getAccountById(instance.toLong())?.let {
// It's fine if the account does not exist anymore -- that means it has been logged out // It's fine if the account does not exist anymore -- that means it has been logged out

View file

@ -43,7 +43,6 @@ import com.keylesspalace.tusky.components.compose.UploadEvent
import com.keylesspalace.tusky.components.drafts.DraftHelper import com.keylesspalace.tusky.components.drafts.DraftHelper
import com.keylesspalace.tusky.components.systemnotifications.NotificationHelper import com.keylesspalace.tusky.components.systemnotifications.NotificationHelper
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.Attachment import com.keylesspalace.tusky.entity.Attachment
import com.keylesspalace.tusky.entity.MediaAttribute import com.keylesspalace.tusky.entity.MediaAttribute
import com.keylesspalace.tusky.entity.NewPoll import com.keylesspalace.tusky.entity.NewPoll
@ -53,7 +52,7 @@ import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.getParcelableExtraCompat import com.keylesspalace.tusky.util.getParcelableExtraCompat
import com.keylesspalace.tusky.util.unsafeLazy import com.keylesspalace.tusky.util.unsafeLazy
import dagger.android.AndroidInjection import dagger.hilt.android.AndroidEntryPoint
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import javax.inject.Inject import javax.inject.Inject
@ -66,7 +65,8 @@ import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import retrofit2.HttpException import retrofit2.HttpException
class SendStatusService : Service(), Injectable { @AndroidEntryPoint
class SendStatusService : Service() {
@Inject @Inject
lateinit var mastodonApi: MastodonApi lateinit var mastodonApi: MastodonApi
@ -93,11 +93,6 @@ class SendStatusService : Service(), Injectable {
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
} }
override fun onCreate() {
AndroidInjection.inject(this)
super.onCreate()
}
override fun onBind(intent: Intent): IBinder? = null override fun onBind(intent: Intent): IBinder? = null
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {

View file

@ -17,9 +17,10 @@ package com.keylesspalace.tusky.service
import android.content.Context import android.content.Context
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject import javax.inject.Inject
class ServiceClient @Inject constructor(private val context: Context) { class ServiceClient @Inject constructor(@ApplicationContext private val context: Context) {
fun sendToot(tootToSend: StatusToSend) { fun sendToot(tootToSend: StatusToSend) {
val intent = SendStatusService.sendStatusIntent(context, tootToSend) val intent = SendStatusService.sendStatusIntent(context, tootToSend)
ContextCompat.startForegroundService(context, intent) ContextCompat.startForegroundService(context, intent)

View file

@ -8,10 +8,11 @@ import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.db.DatabaseCleaner import com.keylesspalace.tusky.db.DatabaseCleaner
import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.ShareShortcutHelper import com.keylesspalace.tusky.util.ShareShortcutHelper
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject import javax.inject.Inject
class LogoutUsecase @Inject constructor( class LogoutUsecase @Inject constructor(
private val context: Context, @ApplicationContext private val context: Context,
private val api: MastodonApi, private val api: MastodonApi,
private val databaseCleaner: DatabaseCleaner, private val databaseCleaner: DatabaseCleaner,
private val accountManager: AccountManager, private val accountManager: AccountManager,

View file

@ -24,12 +24,13 @@ import androidx.preference.PreferenceDataStore
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.keylesspalace.tusky.R import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.settings.PrefKeys import com.keylesspalace.tusky.settings.PrefKeys
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class LocaleManager @Inject constructor( class LocaleManager @Inject constructor(
val context: Context @ApplicationContext val context: Context
) : PreferenceDataStore() { ) : PreferenceDataStore() {
private var prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) private var prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)

View file

@ -35,13 +35,14 @@ import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.db.entity.AccountEntity import com.keylesspalace.tusky.db.entity.AccountEntity
import com.keylesspalace.tusky.di.ApplicationScope import com.keylesspalace.tusky.di.ApplicationScope
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class ShareShortcutHelper @Inject constructor( class ShareShortcutHelper @Inject constructor(
private val context: Context, @ApplicationContext private val context: Context,
private val accountManager: AccountManager, private val accountManager: AccountManager,
@ApplicationScope private val externalScope: CoroutineScope @ApplicationScope private val externalScope: CoroutineScope
) { ) {

View file

@ -27,6 +27,7 @@ import com.keylesspalace.tusky.util.Either.Companion.map
import com.keylesspalace.tusky.util.Either.Left import com.keylesspalace.tusky.util.Either.Left
import com.keylesspalace.tusky.util.Either.Right import com.keylesspalace.tusky.util.Either.Right
import com.keylesspalace.tusky.util.withoutFirstWhich import com.keylesspalace.tusky.util.withoutFirstWhich
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -37,6 +38,7 @@ data class State(
val searchResult: List<TimelineAccount>? val searchResult: List<TimelineAccount>?
) )
@HiltViewModel
class AccountsInListViewModel @Inject constructor(private val api: MastodonApi) : ViewModel() { class AccountsInListViewModel @Inject constructor(private val api: MastodonApi) : ViewModel() {
val state: Flow<State> get() = _state val state: Flow<State> get() = _state

Some files were not shown because too many files have changed in this diff Show more