Use dependency injection for most singletons
This commit is contained in:
@@ -7,12 +7,29 @@ import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.graphics.Bitmap
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import de.mm20.launcher2.applications.applicationsModule
|
||||
import de.mm20.launcher2.badges.badgesModule
|
||||
import de.mm20.launcher2.calculator.calculatorModule
|
||||
import de.mm20.launcher2.calendar.calendarModule
|
||||
import de.mm20.launcher2.contacts.contactsModule
|
||||
import de.mm20.launcher2.debug.Debug
|
||||
import de.mm20.launcher2.icons.IconRepository
|
||||
import de.mm20.launcher2.favorites.favoritesModule
|
||||
import de.mm20.launcher2.files.filesModule
|
||||
import de.mm20.launcher2.hiddenitems.hiddenItemsModule
|
||||
import de.mm20.launcher2.icons.iconsModule
|
||||
import de.mm20.launcher2.music.musicModule
|
||||
import de.mm20.launcher2.preferences.LauncherPreferences
|
||||
import de.mm20.launcher2.preferences.Themes
|
||||
import de.mm20.launcher2.search.searchModule
|
||||
import de.mm20.launcher2.ui.legacy.helper.WallpaperBlur
|
||||
import de.mm20.launcher2.unitconverter.unitConverterModule
|
||||
import de.mm20.launcher2.websites.websitesModule
|
||||
import de.mm20.launcher2.widgets.widgetsModule
|
||||
import de.mm20.launcher2.wikipedia.wikipediaModule
|
||||
import kotlinx.coroutines.*
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.android.ext.koin.androidLogger
|
||||
import org.koin.core.context.startKoin
|
||||
import java.text.Collator
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
@@ -23,29 +40,12 @@ class LauncherApplication : Application(), CoroutineScope {
|
||||
|
||||
var blurredWallpaper: Bitmap? = null
|
||||
|
||||
|
||||
private val appReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context?, intent: Intent?) {
|
||||
IconRepository.getInstance(this@LauncherApplication).requestIconPackListUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
Debug()
|
||||
instance = this
|
||||
LauncherPreferences.initialize(this)
|
||||
IconRepository.getInstance(this).requestIconPackListUpdate()
|
||||
|
||||
registerReceiver(appReceiver, IntentFilter().apply {
|
||||
addAction(Intent.ACTION_PACKAGE_REPLACED)
|
||||
addAction(Intent.ACTION_PACKAGE_ADDED)
|
||||
addAction(Intent.ACTION_PACKAGE_REMOVED)
|
||||
addAction(Intent.ACTION_MY_PACKAGE_REPLACED)
|
||||
addAction(Intent.ACTION_PACKAGE_CHANGED)
|
||||
addDataScheme("package")
|
||||
})
|
||||
val theme = LauncherPreferences.instance.theme
|
||||
AppCompatDelegate.setDefaultNightMode(
|
||||
when (theme) {
|
||||
@@ -58,6 +58,30 @@ class LauncherApplication : Application(), CoroutineScope {
|
||||
WallpaperBlur.requestBlur(this)
|
||||
@Suppress("DEPRECATION") // We need to access the wallpaper directly to blur it
|
||||
registerReceiver(WallpaperReceiver(), IntentFilter(Intent.ACTION_WALLPAPER_CHANGED))
|
||||
|
||||
startKoin {
|
||||
androidLogger()
|
||||
androidContext(this@LauncherApplication)
|
||||
modules(
|
||||
listOf(
|
||||
applicationsModule,
|
||||
calculatorModule,
|
||||
badgesModule,
|
||||
calendarModule,
|
||||
contactsModule,
|
||||
favoritesModule,
|
||||
filesModule,
|
||||
hiddenItemsModule,
|
||||
iconsModule,
|
||||
musicModule,
|
||||
searchModule,
|
||||
unitConverterModule,
|
||||
websitesModule,
|
||||
widgetsModule,
|
||||
wikipediaModule
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -7,9 +7,12 @@ import android.os.Build
|
||||
import android.os.Bundle
|
||||
import de.mm20.launcher2.favorites.FavoritesRepository
|
||||
import de.mm20.launcher2.search.data.AppShortcut
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
class AddItemActivity : Activity() {
|
||||
|
||||
val favoritesRepository: FavoritesRepository by inject()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
@@ -20,7 +23,7 @@ class AddItemActivity : Activity() {
|
||||
packageManager.getApplicationInfo(shortcutInfo.`package`, 0)
|
||||
.loadLabel(packageManager).toString())
|
||||
if (pinRequest.accept()) {
|
||||
FavoritesRepository.getInstance(this).pinItem(shortcut)
|
||||
favoritesRepository.pinItem(shortcut)
|
||||
}
|
||||
}
|
||||
finish()
|
||||
|
||||
@@ -29,6 +29,7 @@ import de.mm20.launcher2.preferences.LauncherPreferences
|
||||
import de.mm20.launcher2.preferences.Themes
|
||||
import de.mm20.launcher2.ui.legacy.view.LauncherIconView
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
class PreferencesAppearanceFragment : PreferenceFragmentCompat() {
|
||||
|
||||
@@ -74,9 +75,10 @@ class PreferencesAppearanceFragment : PreferenceFragmentCompat() {
|
||||
true
|
||||
}
|
||||
|
||||
val manager = IconPackManager.getInstance(requireContext())
|
||||
val iconPackManager: IconPackManager by inject()
|
||||
val iconRepository: IconRepository by inject()
|
||||
lifecycleScope.launch {
|
||||
val packs = manager.getInstalledIconPacks()
|
||||
val packs = iconPackManager.getInstalledIconPacks()
|
||||
findPreference<ListPreference>("icon_pack")?.apply {
|
||||
entries = packs.map { it.name }.toMutableList().apply { add(0, "System") }.toTypedArray()
|
||||
entryValues = (-1 until packs.size).map { it.toString() }.toTypedArray()
|
||||
@@ -86,14 +88,14 @@ class PreferencesAppearanceFragment : PreferenceFragmentCompat() {
|
||||
} else {
|
||||
isEnabled = true
|
||||
summary = "%s"
|
||||
value = packs.indexOfFirst { it.packageName == manager.selectedIconPack }.toString()
|
||||
value = packs.indexOfFirst { it.packageName == iconPackManager.selectedIconPack }.toString()
|
||||
}
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val index = (newValue as String).toInt()
|
||||
IconRepository.getInstance(requireContext()).clearCache()
|
||||
if (index == -1) manager.selectIconPack("")
|
||||
iconRepository.clearCache()
|
||||
if (index == -1) iconPackManager.selectIconPack("")
|
||||
else {
|
||||
manager.selectIconPack(packs[index].packageName)
|
||||
iconPackManager.selectIconPack(packs[index].packageName)
|
||||
}
|
||||
true
|
||||
}
|
||||
@@ -101,7 +103,7 @@ class PreferencesAppearanceFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
|
||||
findPreference<Preference>("legacy_icon_bg")?.setOnPreferenceChangeListener { _, _ ->
|
||||
IconRepository.getInstance(requireContext()).clearCache()
|
||||
iconRepository.clearCache()
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package de.mm20.launcher2.fragment
|
||||
package de.mm20.launcher2.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
@@ -7,32 +7,35 @@ import androidx.preference.PreferenceFragmentCompat
|
||||
import de.mm20.launcher2.R
|
||||
import de.mm20.launcher2.badges.BadgeProvider
|
||||
import de.mm20.launcher2.notifications.NotificationService
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
class PreferencesBadgesFragment : PreferenceFragmentCompat() {
|
||||
|
||||
private val badgesProvider: BadgeProvider by inject()
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
addPreferencesFromResource(R.xml.preferences_badges)
|
||||
findPreference<Preference>("notification_badges")?.setOnPreferenceChangeListener { _, newValue ->
|
||||
if (newValue as Boolean) {
|
||||
de.mm20.launcher2.notifications.NotificationService.getInstance()?.generateBadges()
|
||||
NotificationService.getInstance()?.generateBadges()
|
||||
} else {
|
||||
BadgeProvider.getInstance(requireContext()).removeNotificationBadges()
|
||||
badgesProvider.removeNotificationBadges()
|
||||
}
|
||||
true
|
||||
}
|
||||
findPreference<Preference>("suspended_badges")?.setOnPreferenceChangeListener { _, newValue ->
|
||||
if (newValue as Boolean) {
|
||||
BadgeProvider.getInstance(requireContext()).addSuspendBadges()
|
||||
badgesProvider.addSuspendBadges()
|
||||
} else {
|
||||
BadgeProvider.getInstance(requireContext()).removeSuspendBadges()
|
||||
badgesProvider.removeSuspendBadges()
|
||||
}
|
||||
true
|
||||
}
|
||||
findPreference<Preference>("cloud_badges")?.setOnPreferenceChangeListener { _, newValue ->
|
||||
if (newValue as Boolean) {
|
||||
BadgeProvider.getInstance(requireContext()).addCloudBadges()
|
||||
badgesProvider.addCloudBadges()
|
||||
} else {
|
||||
BadgeProvider.getInstance(requireContext()).removeCloudBadges()
|
||||
badgesProvider.removeCloudBadges()
|
||||
}
|
||||
true
|
||||
}
|
||||
@@ -42,6 +45,6 @@ class PreferencesBadgesFragment : PreferenceFragmentCompat() {
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
(activity as AppCompatActivity).supportActionBar
|
||||
?.setTitle(R.string.preference_screen_badges)
|
||||
?.setTitle(R.string.preference_screen_badges)
|
||||
}
|
||||
}
|
||||
@@ -19,9 +19,12 @@ import de.mm20.launcher2.nextcloud.NextcloudApiHelper
|
||||
import de.mm20.launcher2.owncloud.OwncloudClient
|
||||
import de.mm20.launcher2.preferences.LauncherPreferences
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.android.ext.android.inject
|
||||
|
||||
class PreferencesSearchFragment : PreferenceFragmentCompat() {
|
||||
|
||||
private val googleApiHelper: GoogleApiHelper by inject()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
lifecycleScope.launch {
|
||||
|
||||
@@ -17,7 +17,6 @@ import android.widget.ImageView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.graphics.scale
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
@@ -29,9 +28,9 @@ import com.bumptech.glide.request.target.SimpleTarget
|
||||
import com.bumptech.glide.request.transition.Transition
|
||||
import de.mm20.launcher2.R
|
||||
import de.mm20.launcher2.ktx.dp
|
||||
import de.mm20.launcher2.search.SearchViewModel
|
||||
import de.mm20.launcher2.search.WebsearchViewModel
|
||||
import de.mm20.launcher2.search.data.Websearch
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.lang.ref.WeakReference
|
||||
@@ -42,9 +41,7 @@ class PreferencesWebSearchesFragment : PreferenceFragmentCompat() {
|
||||
|
||||
private var sheetIcon: WeakReference<ImageView>? = null
|
||||
|
||||
private val viewModel by lazy {
|
||||
ViewModelProvider(context as AppCompatActivity)[WebsearchViewModel::class.java]
|
||||
}
|
||||
private val viewModel: WebsearchViewModel by viewModel()
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
preferenceScreen = preferenceManager.createPreferenceScreen(activity)
|
||||
@@ -61,19 +58,23 @@ class PreferencesWebSearchesFragment : PreferenceFragmentCompat() {
|
||||
val pref = Preference(context)
|
||||
pref.title = search.label
|
||||
if (search.icon == null) {
|
||||
val drawable = resources.getDrawable(R.drawable.ic_search, requireActivity().theme).mutate()
|
||||
val drawable =
|
||||
resources.getDrawable(R.drawable.ic_search, requireActivity().theme).mutate()
|
||||
drawable.setTintMode(PorterDuff.Mode.SRC_ATOP)
|
||||
drawable.setTint(search.color)
|
||||
pref.icon = drawable
|
||||
} else {
|
||||
Glide.with(requireContext())
|
||||
.asDrawable()
|
||||
.load(search.icon)
|
||||
.into(object : SimpleTarget<Drawable>() {
|
||||
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
|
||||
pref.icon = resource
|
||||
}
|
||||
})
|
||||
.asDrawable()
|
||||
.load(search.icon)
|
||||
.into(object : SimpleTarget<Drawable>() {
|
||||
override fun onResourceReady(
|
||||
resource: Drawable,
|
||||
transition: Transition<in Drawable>?
|
||||
) {
|
||||
pref.icon = resource
|
||||
}
|
||||
})
|
||||
}
|
||||
pref.setOnPreferenceClickListener {
|
||||
editSearch(search)
|
||||
@@ -109,23 +110,23 @@ class PreferencesWebSearchesFragment : PreferenceFragmentCompat() {
|
||||
imageTintList = ColorStateList.valueOf(websearch.color)
|
||||
} else {
|
||||
Glide.with(this)
|
||||
.load(websearch.icon)
|
||||
.into(this)
|
||||
.load(websearch.icon)
|
||||
.into(this)
|
||||
}
|
||||
sheetIcon = WeakReference(this)
|
||||
}
|
||||
|
||||
val sheet = MaterialDialog(requireContext(), BottomSheet())
|
||||
.cornerRadius(8f)
|
||||
.customView(view = dialogView)
|
||||
.cornerRadius(8f)
|
||||
.customView(view = dialogView)
|
||||
|
||||
val radius = 8 * dialogView.dp
|
||||
dialogView.background = GradientDrawable().apply {
|
||||
cornerRadii = floatArrayOf(
|
||||
radius, radius, // top left
|
||||
radius, radius, // top right
|
||||
0f, 0f, // bottom left
|
||||
0f, 0f // bottom right
|
||||
radius, radius, // top left
|
||||
radius, radius, // top right
|
||||
0f, 0f, // bottom left
|
||||
0f, 0f // bottom right
|
||||
)
|
||||
}
|
||||
|
||||
@@ -134,30 +135,31 @@ class PreferencesWebSearchesFragment : PreferenceFragmentCompat() {
|
||||
|
||||
|
||||
sheet.noAutoDismiss()
|
||||
.positiveButton(android.R.string.ok) {
|
||||
val newUrl = urlEdit.text.toString()
|
||||
val newName = nameEdit.text.toString()
|
||||
if (!newUrl.contains("\${1}")) {
|
||||
urlEdit.error = getString(R.string.websearch_dialog_url_error)
|
||||
return@positiveButton
|
||||
.positiveButton(android.R.string.ok) {
|
||||
val newUrl = urlEdit.text.toString()
|
||||
val newName = nameEdit.text.toString()
|
||||
if (!newUrl.contains("\${1}")) {
|
||||
urlEdit.error = getString(R.string.websearch_dialog_url_error)
|
||||
return@positiveButton
|
||||
}
|
||||
File(requireContext().cacheDir, "websearch-tmp").takeIf { it.exists() }?.let {
|
||||
websearch.icon?.let { File(it).takeIf { it.exists() }?.delete() }
|
||||
val newFile =
|
||||
File(requireContext().filesDir, "websearch-${System.currentTimeMillis()}")
|
||||
it.copyTo(newFile, true)
|
||||
it.delete()
|
||||
newIcon = newFile.absolutePath
|
||||
}
|
||||
if (newIcon == null) {
|
||||
websearch.icon?.let { File(it).takeIf { it.exists() }?.delete() }
|
||||
}
|
||||
websearch.urlTemplate = newUrl
|
||||
websearch.label = newName
|
||||
websearch.icon = newIcon
|
||||
websearch.color = newColor
|
||||
viewModel.insertWebsearch(websearch)
|
||||
sheet.dismiss()
|
||||
}
|
||||
File(requireContext().cacheDir, "websearch-tmp").takeIf { it.exists() }?.let {
|
||||
websearch.icon?.let { File(it).takeIf { it.exists() }?.delete() }
|
||||
val newFile = File(requireContext().filesDir, "websearch-${System.currentTimeMillis()}")
|
||||
it.copyTo(newFile, true)
|
||||
it.delete()
|
||||
newIcon = newFile.absolutePath
|
||||
}
|
||||
if (newIcon == null) {
|
||||
websearch.icon?.let { File(it).takeIf { it.exists() }?.delete() }
|
||||
}
|
||||
websearch.urlTemplate = newUrl
|
||||
websearch.label = newName
|
||||
websearch.icon = newIcon
|
||||
websearch.color = newColor
|
||||
viewModel.insertWebsearch(websearch)
|
||||
sheet.dismiss()
|
||||
}
|
||||
|
||||
sheet.negativeButton(android.R.string.cancel) {
|
||||
sheet.cancel()
|
||||
@@ -188,15 +190,16 @@ class PreferencesWebSearchesFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
title(R.string.websearch_dialog_choose_icon_color)
|
||||
colorChooser(
|
||||
colors = context.resources.getIntArray(R.array.color_chooser_presets),
|
||||
allowCustomArgb = true,
|
||||
showAlphaSelector = false
|
||||
colors = context.resources.getIntArray(R.array.color_chooser_presets),
|
||||
allowCustomArgb = true,
|
||||
showAlphaSelector = false
|
||||
) { _, color ->
|
||||
iconView.setImageResource(R.drawable.ic_search)
|
||||
iconView.imageTintList = ColorStateList.valueOf(color)
|
||||
newColor = color
|
||||
newIcon = null
|
||||
File(requireContext().cacheDir, "websearch-tmp").takeIf { it.exists() }?.delete()
|
||||
File(requireContext().cacheDir, "websearch-tmp").takeIf { it.exists() }
|
||||
?.delete()
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
@@ -207,7 +210,7 @@ class PreferencesWebSearchesFragment : PreferenceFragmentCompat() {
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
(activity as AppCompatActivity).supportActionBar
|
||||
?.setTitle(R.string.preference_search_edit_websearch)
|
||||
?.setTitle(R.string.preference_search_edit_websearch)
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
@@ -216,7 +219,8 @@ class PreferencesWebSearchesFragment : PreferenceFragmentCompat() {
|
||||
if (requestCode == 24 && resultCode == Activity.RESULT_OK && dataUri != null) {
|
||||
val stream = requireActivity().contentResolver.openInputStream(dataUri)
|
||||
val icon = BitmapFactory.decodeStream(stream)
|
||||
val scaledIcon = icon.scale((32 * requireContext().dp).toInt(), (32 * requireContext().dp).toInt())
|
||||
val scaledIcon =
|
||||
icon.scale((32 * requireContext().dp).toInt(), (32 * requireContext().dp).toInt())
|
||||
val out = FileOutputStream(File(requireContext().cacheDir, "websearch-tmp"))
|
||||
scaledIcon.compress(Bitmap.CompressFormat.PNG, 100, out)
|
||||
out.close()
|
||||
|
||||
Reference in New Issue
Block a user