Use dependency injection for most singletons
This commit is contained in:
@@ -93,6 +93,9 @@ dependencies {
|
||||
|
||||
implementation(libs.jsoup)
|
||||
|
||||
implementation(libs.koin.android)
|
||||
implementation(libs.koin.androidxcompose)
|
||||
|
||||
implementation(project(":base"))
|
||||
implementation(project(":i18n"))
|
||||
implementation(project(":compat"))
|
||||
|
||||
@@ -29,6 +29,7 @@ import de.mm20.launcher2.favorites.FavoritesViewModel
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.theme.divider
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class, ExperimentalAnimationApi::class)
|
||||
@@ -39,7 +40,7 @@ fun DefaultSwipeActions(
|
||||
enabled: Boolean = true,
|
||||
content: @Composable RowScope.() -> Unit
|
||||
) {
|
||||
val viewModel: FavoritesViewModel = viewModel()
|
||||
val viewModel: FavoritesViewModel = getViewModel()
|
||||
|
||||
val isPinned by viewModel.isPinned(item).observeAsState()
|
||||
val isHidden by viewModel.isHidden(item).observeAsState()
|
||||
|
||||
@@ -19,16 +19,15 @@ import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||
import com.google.accompanist.pager.PagerState
|
||||
import de.mm20.launcher2.search.SearchViewModel
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.locals.LocalNavController
|
||||
import de.mm20.launcher2.ui.locals.LocalWindowSize
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
|
||||
/**
|
||||
* Search bar
|
||||
@@ -47,7 +46,7 @@ fun SearchBar(
|
||||
) {
|
||||
var searchQuery by remember { mutableStateOf("") }
|
||||
|
||||
val viewModel: SearchViewModel = viewModel()
|
||||
val viewModel: SearchViewModel = getViewModel()
|
||||
|
||||
LaunchedEffect(searchQuery) {
|
||||
viewModel.search(searchQuery)
|
||||
|
||||
@@ -16,6 +16,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.favorites.FavoritesViewModel
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
import kotlin.math.min
|
||||
|
||||
@Composable
|
||||
@@ -162,7 +163,7 @@ data class ToggleToolbarAction(
|
||||
|
||||
@Composable
|
||||
fun favoritesToolbarAction(item: Searchable): ToggleToolbarAction {
|
||||
val viewModel = viewModel<FavoritesViewModel>()
|
||||
val viewModel: FavoritesViewModel = getViewModel()
|
||||
val isPinned by viewModel.isPinned(item).observeAsState(false)
|
||||
|
||||
return ToggleToolbarAction(
|
||||
@@ -183,7 +184,7 @@ fun favoritesToolbarAction(item: Searchable): ToggleToolbarAction {
|
||||
|
||||
@Composable
|
||||
fun hideToolbarAction(item: Searchable): ToggleToolbarAction {
|
||||
val viewModel = viewModel<FavoritesViewModel>()
|
||||
val viewModel: FavoritesViewModel = getViewModel()
|
||||
val isHidden by viewModel.isHidden(item).observeAsState(false)
|
||||
|
||||
return ToggleToolbarAction(
|
||||
|
||||
@@ -27,6 +27,7 @@ import de.mm20.launcher2.ui.locals.LocalWindowSize
|
||||
import de.mm20.launcher2.ui.widget.WidgetCard
|
||||
import de.mm20.launcher2.widgets.Widget
|
||||
import de.mm20.launcher2.widgets.WidgetViewModel
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class, ExperimentalComposeUiApi::class, ExperimentalAnimationGraphicsApi::class
|
||||
)
|
||||
@@ -39,7 +40,7 @@ fun WidgetColumn(
|
||||
|
||||
var widgets by remember { mutableStateOf(listOf<Widget>()) }
|
||||
|
||||
val viewModel: WidgetViewModel = viewModel()
|
||||
val viewModel: WidgetViewModel = getViewModel()
|
||||
|
||||
var editMode by remember { mutableStateOf(false) }
|
||||
|
||||
|
||||
@@ -68,6 +68,8 @@ import de.mm20.launcher2.widgets.WidgetType
|
||||
import de.mm20.launcher2.widgets.WidgetViewModel
|
||||
import kotlinx.android.synthetic.main.activity_launcher.*
|
||||
import kotlinx.coroutines.*
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import java.util.*
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@@ -84,8 +86,9 @@ class LauncherActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var overlayView: ViewGroupOverlay
|
||||
|
||||
private lateinit var searchViewModel: SearchViewModel
|
||||
private lateinit var widgetViewModel: WidgetViewModel
|
||||
private val searchViewModel: SearchViewModel by viewModel()
|
||||
private val widgetViewModel: WidgetViewModel by viewModel()
|
||||
private val favoritesViewModel: FavoritesViewModel by viewModel()
|
||||
|
||||
private val preferences = LauncherPreferences.instance
|
||||
|
||||
@@ -205,8 +208,6 @@ class LauncherActivity : AppCompatActivity() {
|
||||
|
||||
overlayView = rootView.overlay
|
||||
|
||||
searchViewModel = ViewModelProvider(this)[SearchViewModel::class.java]
|
||||
widgetViewModel = ViewModelProvider(this)[WidgetViewModel::class.java]
|
||||
|
||||
|
||||
scrollContainer.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
|
||||
@@ -302,8 +303,7 @@ class LauncherActivity : AppCompatActivity() {
|
||||
}
|
||||
hiddenItemsGrid.columnCount =
|
||||
resources.getInteger(R.integer.config_columnCount)
|
||||
val hiddenItems =
|
||||
ViewModelProvider(this)[FavoritesViewModel::class.java].hiddenItems
|
||||
val hiddenItems = favoritesViewModel.hiddenItems
|
||||
hiddenItems.observe(this) {
|
||||
hiddenItemsGrid.submitItems(it)
|
||||
}
|
||||
@@ -359,7 +359,9 @@ class LauncherActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
lifecycle.addObserver(DynamicIconController.getInstance(this))
|
||||
val dynamicIconController: DynamicIconController by inject()
|
||||
|
||||
lifecycle.addObserver(dynamicIconController)
|
||||
|
||||
lifecycleScope.launch {
|
||||
widgets.addAll(widgetViewModel.getWidgets())
|
||||
@@ -399,10 +401,9 @@ class LauncherActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun addWidget() {
|
||||
val viewModel = ViewModelProvider(this)[WidgetViewModel::class.java]
|
||||
val usedWidgets = widgets.filter { it.type == WidgetType.INTERNAL }.map { it.data }
|
||||
val internalWidgets =
|
||||
viewModel.getInternalWidgets().filter { !usedWidgets.contains(it.data) }
|
||||
widgetViewModel.getInternalWidgets().filter { !usedWidgets.contains(it.data) }
|
||||
if (internalWidgets.isNotEmpty()) {
|
||||
MaterialDialog(this).show {
|
||||
val widgetList =
|
||||
@@ -652,11 +653,11 @@ class LauncherActivity : AppCompatActivity() {
|
||||
ViewModelProvider(this).get(WeatherViewModel::class.java).requestUpdate(this)
|
||||
}
|
||||
PermissionsManager.CALENDAR -> {
|
||||
ViewModelProvider(this)[WidgetViewModel::class.java].requestCalendarUpdate()
|
||||
widgetViewModel.requestCalendarUpdate()
|
||||
}
|
||||
PermissionsManager.ALL -> {
|
||||
ViewModelProvider(this).get(WeatherViewModel::class.java).requestUpdate(this)
|
||||
ViewModelProvider(this)[WidgetViewModel::class.java].requestCalendarUpdate()
|
||||
widgetViewModel.requestCalendarUpdate()
|
||||
search(searchBar.getSearchQuery())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import de.mm20.launcher2.applications.AppViewModel
|
||||
import de.mm20.launcher2.search.data.Application
|
||||
import de.mm20.launcher2.ui.R
|
||||
import kotlinx.android.synthetic.main.view_application.view.*
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class ApplicationView : FrameLayout {
|
||||
|
||||
@@ -25,7 +26,8 @@ class ApplicationView : FrameLayout {
|
||||
layoutTransition = LayoutTransition()
|
||||
layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
|
||||
applicationCard.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
|
||||
applications = ViewModelProvider(context as AppCompatActivity).get(AppViewModel::class.java).applications
|
||||
val viewModel: AppViewModel by (context as AppCompatActivity).viewModel()
|
||||
applications = viewModel.applications
|
||||
applications.observe(context as AppCompatActivity, Observer<List<Application>> {
|
||||
visibility = if (it.isEmpty()) View.GONE else View.VISIBLE
|
||||
applicationGrid.submitItems(it)
|
||||
|
||||
@@ -12,6 +12,7 @@ import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.calculator.CalculatorViewModel
|
||||
import de.mm20.launcher2.search.data.Calculator
|
||||
import kotlinx.android.synthetic.main.view_calculator.view.*
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import kotlin.math.round
|
||||
|
||||
class CalculatorView : FrameLayout {
|
||||
@@ -24,7 +25,8 @@ class CalculatorView : FrameLayout {
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.view_calculator, this)
|
||||
calculator = ViewModelProvider(context as AppCompatActivity).get(CalculatorViewModel::class.java).calculator
|
||||
val viewModel: CalculatorViewModel by (context as AppCompatActivity).viewModel()
|
||||
calculator = viewModel.calculator
|
||||
calculator.observe(context as AppCompatActivity, Observer {
|
||||
if (it == null) visibility = View.GONE
|
||||
else {
|
||||
|
||||
@@ -16,6 +16,7 @@ import de.mm20.launcher2.preferences.LauncherPreferences
|
||||
import de.mm20.launcher2.search.data.CalendarEvent
|
||||
import de.mm20.launcher2.search.data.MissingPermission
|
||||
import de.mm20.launcher2.ui.legacy.search.SearchListView
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class CalendarView : FrameLayout {
|
||||
|
||||
@@ -32,7 +33,8 @@ class CalendarView : FrameLayout {
|
||||
val card = findViewById<ViewGroup>(R.id.card)
|
||||
card.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
|
||||
val list = findViewById<SearchListView>(R.id.list)
|
||||
calendarEvents = ViewModelProvider(context as AppCompatActivity).get(CalendarViewModel::class.java).calendarEvents
|
||||
val viewModel: CalendarViewModel by (context as AppCompatActivity).viewModel()
|
||||
calendarEvents = viewModel.calendarEvents
|
||||
calendarEvents.observe(context as AppCompatActivity, {
|
||||
if (it == null) {
|
||||
visibility = View.GONE
|
||||
|
||||
@@ -16,6 +16,7 @@ import de.mm20.launcher2.search.data.Contact
|
||||
import de.mm20.launcher2.search.data.MissingPermission
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.legacy.search.SearchListView
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class ContactView : FrameLayout {
|
||||
private val contacts: LiveData<List<Contact>?>
|
||||
@@ -30,7 +31,8 @@ class ContactView : FrameLayout {
|
||||
layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
|
||||
val card = findViewById<ViewGroup>(R.id.card)
|
||||
card.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
|
||||
contacts = ViewModelProvider(context as AppCompatActivity).get(ContactViewModel::class.java).contacts
|
||||
val viewModel: ContactViewModel by (context as AppCompatActivity).viewModel()
|
||||
contacts = viewModel.contacts
|
||||
val list = findViewById<SearchListView>(R.id.list)
|
||||
contacts.observe(context as AppCompatActivity, {
|
||||
if (it == null) {
|
||||
|
||||
@@ -12,15 +12,20 @@ import de.mm20.launcher2.ui.R
|
||||
import kotlinx.android.synthetic.main.edit_favorites_row.view.*
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class EditFavoritesRow @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, val favoritesItem: FavoritesItem
|
||||
) : LinearLayout(context, attrs, defStyleAttr) {
|
||||
) : LinearLayout(context, attrs, defStyleAttr), KoinComponent {
|
||||
|
||||
val iconRepository: IconRepository by inject()
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.edit_favorites_row, this)
|
||||
label.text = favoritesItem.searchable?.label
|
||||
lifecycleScope.launch {
|
||||
IconRepository.getInstance(context).getIcon(favoritesItem.searchable!!, (48*dp).toInt()).collect{
|
||||
iconRepository.getIcon(favoritesItem.searchable!!, (48*dp).toInt()).collect{
|
||||
icon.icon = it
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,14 @@ import kotlinx.android.synthetic.main.dialog_edit_favorites.view.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class EditFavoritesView @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null
|
||||
) : FrameLayout(context, attrs) {
|
||||
|
||||
val viewModel : FavoritesViewModel by (context as AppCompatActivity).viewModel()
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.dialog_edit_favorites, this)
|
||||
lifecycleScope.launch {
|
||||
@@ -35,7 +39,6 @@ class EditFavoritesView @JvmOverloads constructor(
|
||||
private lateinit var favorites: MutableList<FavoritesItem>
|
||||
|
||||
suspend fun initView() {
|
||||
val viewModel = ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java]
|
||||
favorites = withContext(Dispatchers.IO) {
|
||||
viewModel.getAllFavoriteItems().toMutableList()
|
||||
}
|
||||
@@ -117,7 +120,6 @@ class EditFavoritesView @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
fun save() {
|
||||
val viewModel = ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java]
|
||||
viewModel.saveFavorites(favorites)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import de.mm20.launcher2.favorites.FavoritesViewModel
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import kotlinx.android.synthetic.main.view_favorites.view.*
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class FavoritesView : FrameLayout {
|
||||
|
||||
@@ -23,7 +24,7 @@ class FavoritesView : FrameLayout {
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.view_favorites, this)
|
||||
val viewModel = ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java]
|
||||
val viewModel: FavoritesViewModel by (context as AppCompatActivity).viewModel()
|
||||
favorites = viewModel.getFavorites(context.resources.getInteger(R.integer.config_columnCount))
|
||||
favorites.observe(context as AppCompatActivity, Observer {
|
||||
visibility = if (it?.isEmpty() == true) View.GONE else View.VISIBLE
|
||||
|
||||
@@ -15,6 +15,7 @@ import de.mm20.launcher2.search.data.File
|
||||
import de.mm20.launcher2.search.data.MissingPermission
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.legacy.search.SearchListView
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class FileView : FrameLayout {
|
||||
private val files: LiveData<List<File>?>
|
||||
@@ -30,7 +31,8 @@ class FileView : FrameLayout {
|
||||
val card = findViewById<ViewGroup>(R.id.card)
|
||||
card.layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
|
||||
val list = findViewById<SearchListView>(R.id.list)
|
||||
files = ViewModelProvider(context as AppCompatActivity).get(FilesViewModel::class.java).files
|
||||
val viewModel: FilesViewModel by (context as AppCompatActivity).viewModel()
|
||||
files = viewModel.files
|
||||
files.observe(context as AppCompatActivity, {
|
||||
if (it == null) {
|
||||
visibility = View.GONE
|
||||
|
||||
@@ -26,6 +26,7 @@ import de.mm20.launcher2.transition.ChangingLayoutTransition
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.legacy.view.LauncherCardView
|
||||
import kotlinx.android.synthetic.main.view_search_bar.view.*
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class SearchBar @JvmOverloads constructor(
|
||||
context: Context,
|
||||
@@ -70,7 +71,9 @@ class SearchBar @JvmOverloads constructor(
|
||||
|
||||
})
|
||||
|
||||
ViewModelProvider(context as AppCompatActivity)[SearchViewModel::class.java].isSearching.observe(context, Observer {
|
||||
val viewModel = (context as AppCompatActivity).viewModel<SearchViewModel>().value
|
||||
|
||||
viewModel.isSearching.observe(context, Observer {
|
||||
searchProgressBar.visibility = if (it) View.VISIBLE else View.GONE
|
||||
})
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import androidx.browser.customtabs.CustomTabsIntent
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
@@ -31,6 +32,7 @@ import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.unitconverter.UnitConverterViewModel
|
||||
import de.mm20.launcher2.unitconverter.UnitValue
|
||||
import kotlinx.android.synthetic.main.view_unitconverter.view.*
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
import kotlin.math.min
|
||||
@@ -46,7 +48,8 @@ class UnitConverterView : FrameLayout {
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.view_unitconverter, this)
|
||||
unitConverter = ViewModelProvider(context as AppCompatActivity).get(UnitConverterViewModel::class.java).unitConverter
|
||||
val unitConverterViewModel by (context as AppCompatActivity).viewModel<UnitConverterViewModel>()
|
||||
unitConverter = unitConverterViewModel.unitConverter
|
||||
unitConverter.observe(context as AppCompatActivity, Observer {
|
||||
if (it == null) visibility = View.GONE
|
||||
else {
|
||||
|
||||
@@ -21,6 +21,7 @@ import de.mm20.launcher2.search.WebsearchViewModel
|
||||
import de.mm20.launcher2.search.data.Websearch
|
||||
import de.mm20.launcher2.ui.R
|
||||
import kotlinx.android.synthetic.main.view_websearch.view.*
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class WebSearchView : FrameLayout {
|
||||
constructor(context: Context) : super(context)
|
||||
@@ -31,7 +32,7 @@ class WebSearchView : FrameLayout {
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.view_websearch, this)
|
||||
val viewModel = ViewModelProvider(context as AppCompatActivity)[WebsearchViewModel::class.java]
|
||||
val viewModel: WebsearchViewModel by (context as AppCompatActivity).viewModel()
|
||||
websearches = viewModel.websearches
|
||||
websearches.observe(context as AppCompatActivity, Observer {
|
||||
updateWebsearches(it)
|
||||
|
||||
@@ -14,6 +14,7 @@ import de.mm20.launcher2.search.data.Website
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.legacy.searchable.SearchableView
|
||||
import de.mm20.launcher2.websites.WebsiteViewModel
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class WebsiteView : FrameLayout {
|
||||
|
||||
@@ -30,7 +31,8 @@ class WebsiteView : FrameLayout {
|
||||
val card = findViewById<ViewGroup>(R.id.card)
|
||||
websiteView.layoutParams = params
|
||||
card.addView(websiteView)
|
||||
website = ViewModelProvider(context as AppCompatActivity)[WebsiteViewModel::class.java].website
|
||||
val viewModel: WebsiteViewModel by (context as AppCompatActivity).viewModel()
|
||||
website = viewModel.website
|
||||
website.observe(context as AppCompatActivity, Observer {
|
||||
visibility = if (it == null) View.GONE else View.VISIBLE
|
||||
card.setOnClickListener { _ ->
|
||||
|
||||
@@ -14,6 +14,7 @@ import de.mm20.launcher2.search.data.Wikipedia
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.legacy.searchable.SearchableView
|
||||
import de.mm20.launcher2.wikipedia.WikipediaViewModel
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class WikipediaView : FrameLayout {
|
||||
|
||||
@@ -30,7 +31,8 @@ class WikipediaView : FrameLayout {
|
||||
val card = findViewById<ViewGroup>(R.id.card)
|
||||
websiteView.layoutParams = params
|
||||
card.addView(websiteView)
|
||||
wikipedia = ViewModelProvider(context as AppCompatActivity)[WikipediaViewModel::class.java].wikipedia
|
||||
val viewModel: WikipediaViewModel by (context as AppCompatActivity).viewModel()
|
||||
wikipedia = viewModel.wikipedia
|
||||
wikipedia.observe(context as AppCompatActivity, Observer {
|
||||
visibility = if (it == null) View.GONE else View.VISIBLE
|
||||
card.setOnClickListener { _ ->
|
||||
|
||||
@@ -18,9 +18,13 @@ import de.mm20.launcher2.preferences.AppStartAnimation
|
||||
import de.mm20.launcher2.preferences.LauncherPreferences
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import java.lang.ref.WeakReference
|
||||
|
||||
object ActivityStarter {
|
||||
object ActivityStarter: KoinComponent {
|
||||
|
||||
val favoritesRepository: FavoritesRepository by inject()
|
||||
|
||||
private var initialized = false
|
||||
private lateinit var overlayView: WeakReference<ViewGroupOverlay>
|
||||
@@ -141,7 +145,7 @@ object ActivityStarter {
|
||||
|
||||
if (item != null) {
|
||||
if (item.launch(context, bundle)) {
|
||||
FavoritesRepository.getInstance(context).incrementLaunchCount(item)
|
||||
favoritesRepository.incrementLaunchCount(item)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
+13
-8
@@ -27,6 +27,7 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.core.graphics.alpha
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.transition.Scene
|
||||
@@ -52,10 +53,16 @@ import de.mm20.launcher2.ui.legacy.searchable.SearchableView
|
||||
import de.mm20.launcher2.ui.legacy.view.*
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class ApplicationDetailRepresentation : Representation {
|
||||
class ApplicationDetailRepresentation : Representation, KoinComponent {
|
||||
|
||||
private val iconRepository: IconRepository by inject()
|
||||
private val badgeProvider: BadgeProvider by inject()
|
||||
|
||||
override fun getScene(
|
||||
rootView: SearchableView,
|
||||
@@ -71,12 +78,11 @@ class ApplicationDetailRepresentation : Representation {
|
||||
setOnLongClickListener(null)
|
||||
findViewById<TextView>(R.id.appName).text = application.label
|
||||
findViewById<LauncherIconView>(R.id.icon).apply {
|
||||
badge = BadgeProvider.getInstance(context).getLiveBadge(application.badgeKey)
|
||||
badge = badgeProvider.getLiveBadge(application.badgeKey)
|
||||
shape = LauncherIconView.getDefaultShape(context)
|
||||
icon = IconRepository.getInstance(context).getIconIfCached(application)
|
||||
icon = iconRepository.getIconIfCached(application)
|
||||
lifecycleScope.launch {
|
||||
IconRepository.getInstance(context)
|
||||
.getIcon(application, (84 * rootView.dp).toInt()).collect {
|
||||
iconRepository.getIcon(application, (84 * rootView.dp).toInt()).collect {
|
||||
icon = it
|
||||
}
|
||||
}
|
||||
@@ -264,8 +270,7 @@ class ApplicationDetailRepresentation : Representation {
|
||||
if (launcherApps.hasShortcutHostPermission()) {
|
||||
val shortcuts = app.shortcuts
|
||||
|
||||
val viewModel =
|
||||
ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java]
|
||||
val viewModel : FavoritesViewModel by (context as AppCompatActivity).viewModel()
|
||||
|
||||
for (si in shortcuts) {
|
||||
val view = Chip(context)
|
||||
@@ -292,7 +297,7 @@ class ApplicationDetailRepresentation : Representation {
|
||||
)
|
||||
val isPinned = viewModel.isPinned(si)
|
||||
|
||||
isPinned.observe(context, Observer {
|
||||
isPinned.observe(context as LifecycleOwner, Observer {
|
||||
view.isCloseIconVisible = isPinned.value == true
|
||||
})
|
||||
|
||||
|
||||
@@ -3,20 +3,30 @@ package de.mm20.launcher2.ui.legacy.search
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.transition.Scene
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.badges.BadgeProvider
|
||||
import de.mm20.launcher2.ktx.dp
|
||||
import de.mm20.launcher2.icons.IconRepository
|
||||
import de.mm20.launcher2.ktx.dp
|
||||
import de.mm20.launcher2.ktx.lifecycleScope
|
||||
import de.mm20.launcher2.legacy.helper.ActivityStarter
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.legacy.searchable.SearchableView
|
||||
import de.mm20.launcher2.ui.legacy.view.LauncherIconView
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class BasicGridRepresentation : Representation {
|
||||
override fun getScene(rootView: SearchableView, searchable: Searchable, previousRepresentation: Int?): Scene {
|
||||
class BasicGridRepresentation : Representation, KoinComponent {
|
||||
|
||||
private val iconRepository: IconRepository by inject()
|
||||
private val badgeProvider: BadgeProvider by inject()
|
||||
|
||||
override fun getScene(
|
||||
rootView: SearchableView,
|
||||
searchable: Searchable,
|
||||
previousRepresentation: Int?
|
||||
): Scene {
|
||||
val context = rootView.context as AppCompatActivity
|
||||
val scene = Scene.getSceneForLayout(rootView, R.layout.view_basic_grid, rootView.context)
|
||||
scene.setEnterAction {
|
||||
@@ -30,16 +40,21 @@ class BasicGridRepresentation : Representation {
|
||||
.alpha(1f)
|
||||
.start()*/
|
||||
findViewById<LauncherIconView>(R.id.icon).apply {
|
||||
badge = BadgeProvider.getInstance(context).getLiveBadge(searchable.badgeKey)
|
||||
badge = badgeProvider.getLiveBadge(searchable.badgeKey)
|
||||
shape = LauncherIconView.getDefaultShape(context)
|
||||
setOnClickListener {
|
||||
if (!ActivityStarter.start(context, rootView.findViewById(R.id.card), item = searchable)) {
|
||||
if (!ActivityStarter.start(
|
||||
context,
|
||||
rootView.findViewById(R.id.card),
|
||||
item = searchable
|
||||
)
|
||||
) {
|
||||
rootView.representation = SearchableView.REPRESENTATION_FULL
|
||||
}
|
||||
}
|
||||
icon = IconRepository.getInstance(context).getIconIfCached(searchable)
|
||||
icon = iconRepository.getIconIfCached(searchable)
|
||||
lifecycleScope.launch {
|
||||
IconRepository.getInstance(context).getIcon(searchable, (84 * rootView.dp).toInt()).collect {
|
||||
iconRepository.getIcon(searchable, (84 * rootView.dp).toInt()).collect {
|
||||
icon = it
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,15 @@ import de.mm20.launcher2.ui.legacy.searchable.SearchableView
|
||||
import de.mm20.launcher2.ui.legacy.view.*
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import java.net.URLEncoder
|
||||
|
||||
class ContactDetailRepresentation : Representation {
|
||||
class ContactDetailRepresentation : Representation, KoinComponent {
|
||||
|
||||
val iconRepository: IconRepository by inject()
|
||||
val badgeProvider: BadgeProvider by inject()
|
||||
|
||||
override fun getScene(
|
||||
rootView: SearchableView,
|
||||
searchable: Searchable,
|
||||
@@ -42,12 +48,11 @@ class ContactDetailRepresentation : Representation {
|
||||
scene.setEnterAction {
|
||||
with(rootView) {
|
||||
findViewById<LauncherIconView>(R.id.icon).apply {
|
||||
badge = BadgeProvider.getInstance(context).getLiveBadge(contact.badgeKey)
|
||||
badge = badgeProvider.getLiveBadge(contact.badgeKey)
|
||||
shape = LauncherIconView.getDefaultShape(context)
|
||||
icon = IconRepository.getInstance(context).getIconIfCached(contact)
|
||||
icon = iconRepository.getIconIfCached(contact)
|
||||
lifecycleScope.launch {
|
||||
IconRepository.getInstance(context)
|
||||
.getIcon(contact, (84 * rootView.dp).toInt()).collect {
|
||||
iconRepository.getIcon(contact, (84 * rootView.dp).toInt()).collect {
|
||||
icon = it
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,14 @@ import de.mm20.launcher2.ui.legacy.view.LauncherIconView
|
||||
import de.mm20.launcher2.ui.legacy.view.SwipeCardView
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class ContactListRepresentation : Representation, KoinComponent {
|
||||
|
||||
val iconRepository: IconRepository by inject()
|
||||
val badgeProvider: BadgeProvider by inject()
|
||||
|
||||
class ContactListRepresentation : Representation {
|
||||
override fun getScene(rootView: SearchableView, searchable: Searchable, previousRepresentation: Int?): Scene {
|
||||
val contact = searchable as Contact
|
||||
val context = rootView.context as AppCompatActivity
|
||||
@@ -26,11 +32,11 @@ class ContactListRepresentation : Representation {
|
||||
scene.setEnterAction {
|
||||
with(rootView) {
|
||||
findViewById<LauncherIconView>(R.id.icon).apply {
|
||||
badge = BadgeProvider.getInstance(context).getLiveBadge(contact.badgeKey)
|
||||
badge = badgeProvider.getLiveBadge(contact.badgeKey)
|
||||
shape = LauncherIconView.getDefaultShape(context)
|
||||
icon = IconRepository.getInstance(context).getIconIfCached(contact)
|
||||
icon = iconRepository.getIconIfCached(contact)
|
||||
lifecycleScope.launch {
|
||||
IconRepository.getInstance(context).getIcon(contact, (84 * rootView.dp).toInt()).collect {
|
||||
iconRepository.getIcon(contact, (84 * rootView.dp).toInt()).collect {
|
||||
icon = it
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,16 @@ import de.mm20.launcher2.ui.legacy.searchable.SearchableView
|
||||
import de.mm20.launcher2.ui.legacy.view.*
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import java.text.DecimalFormat
|
||||
|
||||
class FileDetailRepresentation : Representation {
|
||||
class FileDetailRepresentation : Representation, KoinComponent {
|
||||
|
||||
val iconRepository: IconRepository by inject()
|
||||
val badgeProvider: BadgeProvider by inject()
|
||||
|
||||
override fun getScene(rootView: SearchableView, searchable: Searchable, previousRepresentation: Int?): Scene {
|
||||
val file = searchable as File
|
||||
val context = rootView.context as AppCompatActivity
|
||||
@@ -34,11 +41,11 @@ class FileDetailRepresentation : Representation {
|
||||
findViewById<TextView>(R.id.fileLabel).text = file.label
|
||||
findViewById<TextView>(R.id.fileInfo).text = getInfo(context, file)
|
||||
findViewById<LauncherIconView>(R.id.icon).apply {
|
||||
badge = BadgeProvider.getInstance(context).getLiveBadge(file.badgeKey)
|
||||
badge = badgeProvider.getLiveBadge(file.badgeKey)
|
||||
shape = LauncherIconView.getDefaultShape(context)
|
||||
icon = IconRepository.getInstance(context).getIconIfCached(file)
|
||||
icon = iconRepository.getIconIfCached(file)
|
||||
lifecycleScope.launch {
|
||||
IconRepository.getInstance(context).getIcon(file, (84 * rootView.dp).toInt()).collect {
|
||||
iconRepository.getIcon(file, (84 * rootView.dp).toInt()).collect {
|
||||
icon = it
|
||||
}
|
||||
}
|
||||
@@ -100,7 +107,7 @@ class FileDetailRepresentation : Representation {
|
||||
"${MediaStore.Files.FileColumns._ID} = ?",
|
||||
arrayOf(file.id.toString()))
|
||||
it.dismiss()
|
||||
val fileViewModel = ViewModelProvider(context as AppCompatActivity)[FilesViewModel::class.java]
|
||||
val fileViewModel: FilesViewModel by (context as AppCompatActivity).viewModel()
|
||||
fileViewModel.removeFile(file)
|
||||
}
|
||||
negativeButton(android.R.string.no) {
|
||||
|
||||
@@ -19,8 +19,14 @@ import de.mm20.launcher2.ui.legacy.view.LauncherIconView
|
||||
import de.mm20.launcher2.ui.legacy.view.SwipeCardView
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class FileListRepresentation : Representation, KoinComponent {
|
||||
|
||||
val iconRepository: IconRepository by inject()
|
||||
val badgeProvider: BadgeProvider by inject()
|
||||
|
||||
class FileListRepresentation : Representation {
|
||||
override fun getScene(rootView: SearchableView, searchable: Searchable, previousRepresentation: Int?): Scene {
|
||||
val file = searchable as File
|
||||
val context = rootView.context as AppCompatActivity
|
||||
@@ -30,11 +36,11 @@ class FileListRepresentation : Representation {
|
||||
findViewById<TextView>(R.id.fileLabel).text = file.label
|
||||
findViewById<TextView>(R.id.fileInfo).text = getFileType(context, file)
|
||||
findViewById<LauncherIconView>(R.id.icon).apply {
|
||||
badge = BadgeProvider.getInstance(context).getLiveBadge(file.badgeKey)
|
||||
badge = badgeProvider.getLiveBadge(file.badgeKey)
|
||||
shape = LauncherIconView.getDefaultShape(context)
|
||||
icon = IconRepository.getInstance(context).getIconIfCached(file)
|
||||
icon = iconRepository.getIconIfCached(file)
|
||||
lifecycleScope.launch {
|
||||
IconRepository.getInstance(context).getIcon(file, (84 * rootView.dp).toInt()).collect {
|
||||
iconRepository.getIcon(file, (84 * rootView.dp).toInt()).collect {
|
||||
icon = it
|
||||
}
|
||||
}
|
||||
|
||||
+10
-4
@@ -19,9 +19,15 @@ import de.mm20.launcher2.ui.legacy.view.ToolbarAction
|
||||
import de.mm20.launcher2.ui.legacy.view.ToolbarView
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N_MR1)
|
||||
class AppShortcutDetailRepresentation: Representation {
|
||||
class AppShortcutDetailRepresentation: Representation, KoinComponent {
|
||||
|
||||
val iconRepository: IconRepository by inject()
|
||||
val badgeProvider: BadgeProvider by inject()
|
||||
|
||||
override fun getScene(rootView: SearchableView, searchable: Searchable, previousRepresentation: Int?): Scene {
|
||||
val appShortcut = searchable as AppShortcut
|
||||
val context = rootView.context as AppCompatActivity
|
||||
@@ -32,11 +38,11 @@ class AppShortcutDetailRepresentation: Representation {
|
||||
setOnLongClickListener(null)
|
||||
findViewById<TextView>(R.id.appName).text = appShortcut.label
|
||||
findViewById<LauncherIconView>(R.id.icon).apply {
|
||||
badge = BadgeProvider.getInstance(context).getLiveBadge(appShortcut.badgeKey)
|
||||
badge = badgeProvider.getLiveBadge(appShortcut.badgeKey)
|
||||
shape = LauncherIconView.getDefaultShape(context)
|
||||
icon = IconRepository.getInstance(context).getIconIfCached(appShortcut)
|
||||
icon = iconRepository.getIconIfCached(appShortcut)
|
||||
lifecycleScope.launch {
|
||||
IconRepository.getInstance(context).getIcon(appShortcut, (84 * rootView.dp).toInt()).collect {
|
||||
iconRepository.getIcon(appShortcut, (84 * rootView.dp).toInt()).collect {
|
||||
icon = it
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,14 @@ import de.mm20.launcher2.ui.legacy.view.ToolbarAction
|
||||
import de.mm20.launcher2.ui.legacy.view.ToolbarView
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class WebsiteDetailRepresentation : Representation, KoinComponent {
|
||||
|
||||
val iconRepository: IconRepository by inject()
|
||||
val badgeProvider: BadgeProvider by inject()
|
||||
|
||||
class WebsiteDetailRepresentation : Representation {
|
||||
override fun getScene(rootView: SearchableView, searchable: Searchable, previousRepresentation: Int?): Scene {
|
||||
val website = searchable as Website
|
||||
val context = rootView.context as AppCompatActivity
|
||||
@@ -60,11 +66,11 @@ class WebsiteDetailRepresentation : Representation {
|
||||
label.transitionName = null
|
||||
websiteFavIcon.transitionName = "icon"
|
||||
websiteFavIcon.apply {
|
||||
badge = BadgeProvider.getInstance(context).getLiveBadge(website.badgeKey)
|
||||
badge = badgeProvider.getLiveBadge(website.badgeKey)
|
||||
shape = LauncherIconView.getDefaultShape(context)
|
||||
icon = IconRepository.getInstance(context).getIconIfCached(website)
|
||||
icon = iconRepository.getIconIfCached(website)
|
||||
lifecycleScope.launch {
|
||||
IconRepository.getInstance(context).getIcon(website, (84 * rootView.dp).toInt()).collect {
|
||||
iconRepository.getIcon(website, (84 * rootView.dp).toInt()).collect {
|
||||
icon = it
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.transition.Scene
|
||||
import com.bumptech.glide.Glide
|
||||
import de.mm20.launcher2.badges.BadgeProvider
|
||||
import de.mm20.launcher2.ktx.dp
|
||||
import de.mm20.launcher2.icons.IconRepository
|
||||
import de.mm20.launcher2.ktx.dp
|
||||
import de.mm20.launcher2.ktx.lifecycleScope
|
||||
import de.mm20.launcher2.legacy.helper.ActivityStarter
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
@@ -24,9 +24,20 @@ import de.mm20.launcher2.ui.legacy.view.ToolbarAction
|
||||
import de.mm20.launcher2.ui.legacy.view.ToolbarView
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class WebsiteListRepresentation : Representation {
|
||||
override fun getScene(rootView: SearchableView, searchable: Searchable, previousRepresentation: Int?): Scene {
|
||||
class WebsiteListRepresentation : Representation, KoinComponent {
|
||||
|
||||
val iconRepository: IconRepository by inject()
|
||||
|
||||
val badgeProvider: BadgeProvider by inject()
|
||||
|
||||
override fun getScene(
|
||||
rootView: SearchableView,
|
||||
searchable: Searchable,
|
||||
previousRepresentation: Int?
|
||||
): Scene {
|
||||
val website = searchable as Website
|
||||
val context = rootView.context as AppCompatActivity
|
||||
val scene = Scene.getSceneForLayout(rootView, R.layout.view_website_list, rootView.context)
|
||||
@@ -60,11 +71,11 @@ class WebsiteListRepresentation : Representation {
|
||||
label.transitionName = null
|
||||
websiteFavIcon.transitionName = "icon"
|
||||
websiteFavIcon.apply {
|
||||
badge = BadgeProvider.getInstance(context).getLiveBadge(website.badgeKey)
|
||||
badge = badgeProvider.getLiveBadge(website.badgeKey)
|
||||
shape = LauncherIconView.getDefaultShape(context)
|
||||
icon = IconRepository.getInstance(context).getIconIfCached(website)
|
||||
icon = iconRepository.getIconIfCached(website)
|
||||
lifecycleScope.launch {
|
||||
IconRepository.getInstance(context).getIcon(website, (84 * rootView.dp).toInt()).collect {
|
||||
iconRepository.getIcon(website, (84 * rootView.dp).toInt()).collect {
|
||||
icon = it
|
||||
}
|
||||
}
|
||||
@@ -101,7 +112,10 @@ class WebsiteListRepresentation : Representation {
|
||||
|
||||
private fun share(context: Context, website: Website) {
|
||||
val shareIntent = Intent(Intent.ACTION_SEND)
|
||||
shareIntent.putExtra(Intent.EXTRA_TEXT, "${website.label}\n\n${website.description}\n\n${website.url}")
|
||||
shareIntent.putExtra(
|
||||
Intent.EXTRA_TEXT,
|
||||
"${website.label}\n\n${website.description}\n\n${website.url}"
|
||||
)
|
||||
shareIntent.type = "text/plain"
|
||||
context.startActivity(Intent.createChooser(shareIntent, null))
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import de.mm20.launcher2.preferences.LauncherPreferences
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.transition.ChangingLayoutTransition
|
||||
import de.mm20.launcher2.ui.R
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import kotlin.math.abs
|
||||
|
||||
class SwipeCardView @JvmOverloads constructor(
|
||||
@@ -376,10 +377,10 @@ class FavoriteSwipeAction(val context: Context, val searchable: Searchable) :
|
||||
ContextCompat.getColor(context, R.color.amber),
|
||||
{ false }
|
||||
) {
|
||||
val pinned =
|
||||
ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java].isPinned(
|
||||
searchable
|
||||
)
|
||||
val viewModel: FavoritesViewModel by (context as AppCompatActivity).viewModel()
|
||||
|
||||
private val pinned = viewModel.isPinned(searchable)
|
||||
|
||||
|
||||
init {
|
||||
pinned.observe(context as LifecycleOwner) {
|
||||
@@ -391,7 +392,7 @@ class FavoriteSwipeAction(val context: Context, val searchable: Searchable) :
|
||||
if (pinned) {
|
||||
icon = R.drawable.ic_star_outline
|
||||
action = {
|
||||
ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java].unpinItem(
|
||||
viewModel.unpinItem(
|
||||
searchable
|
||||
)
|
||||
false
|
||||
@@ -399,7 +400,7 @@ class FavoriteSwipeAction(val context: Context, val searchable: Searchable) :
|
||||
} else {
|
||||
icon = R.drawable.ic_star_solid
|
||||
action = {
|
||||
ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java].pinItem(
|
||||
viewModel.pinItem(
|
||||
searchable
|
||||
)
|
||||
false
|
||||
@@ -413,10 +414,8 @@ class HideSwipeAction(val context: Context, val searchable: Searchable) : SwipeC
|
||||
ContextCompat.getColor(context, R.color.blue),
|
||||
{ false }
|
||||
) {
|
||||
val hidden =
|
||||
ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java].isHidden(
|
||||
searchable
|
||||
)
|
||||
val viewModel: FavoritesViewModel by (context as AppCompatActivity).viewModel()
|
||||
private val hidden = viewModel.isHidden(searchable)
|
||||
|
||||
init {
|
||||
hidden.observe(context as LifecycleOwner) {
|
||||
@@ -428,7 +427,7 @@ class HideSwipeAction(val context: Context, val searchable: Searchable) : SwipeC
|
||||
if (hidden) {
|
||||
icon = R.drawable.ic_visibility
|
||||
action = {
|
||||
ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java].unhideItem(
|
||||
viewModel.unhideItem(
|
||||
searchable
|
||||
)
|
||||
true
|
||||
@@ -436,7 +435,7 @@ class HideSwipeAction(val context: Context, val searchable: Searchable) : SwipeC
|
||||
} else {
|
||||
icon = R.drawable.ic_visibility_off
|
||||
action = {
|
||||
ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java].hideItem(
|
||||
viewModel.hideItem(
|
||||
searchable
|
||||
)
|
||||
true
|
||||
|
||||
@@ -11,16 +11,20 @@ import androidx.appcompat.widget.PopupMenu
|
||||
import androidx.appcompat.widget.TooltipCompat
|
||||
import androidx.core.view.setPadding
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.favorites.FavoritesViewModel
|
||||
import de.mm20.launcher2.ktx.dp
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class ToolbarView : LinearLayout {
|
||||
constructor(context: Context) : super(context)
|
||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(context, attrs, defStyleRes)
|
||||
constructor(context: Context, attrs: AttributeSet?, defStyleRes: Int) : super(
|
||||
context,
|
||||
attrs,
|
||||
defStyleRes
|
||||
)
|
||||
|
||||
private val slots = context.resources.getInteger(R.integer.config_toolbarSlots)
|
||||
|
||||
@@ -53,7 +57,8 @@ class ToolbarView : LinearLayout {
|
||||
overflowMenuIcon.isClickable = true
|
||||
overflowMenuIcon.isFocusable = true
|
||||
overflowMenuIcon.setPadding((12 * dp).toInt())
|
||||
overflowMenuIcon.layoutParams = LayoutParams((48 * dp).toInt(), (48 * dp).toInt())
|
||||
overflowMenuIcon.layoutParams =
|
||||
LayoutParams((48 * dp).toInt(), (48 * dp).toInt())
|
||||
overflowMenuIcon.setImageResource(R.drawable.ic_more_vert)
|
||||
removeViewAt(leftActions.size - 1)
|
||||
addView(overflowMenuIcon, leftActions.size - 1)
|
||||
@@ -88,7 +93,8 @@ class ToolbarView : LinearLayout {
|
||||
overflowMenuIcon.isClickable = true
|
||||
overflowMenuIcon.isFocusable = true
|
||||
overflowMenuIcon.setPadding((12 * dp).toInt())
|
||||
overflowMenuIcon.layoutParams = LayoutParams((48 * dp).toInt(), (48 * dp).toInt())
|
||||
overflowMenuIcon.layoutParams =
|
||||
LayoutParams((48 * dp).toInt(), (48 * dp).toInt())
|
||||
overflowMenuIcon.setImageResource(R.drawable.ic_more_vert)
|
||||
removeViewAt(childCount - 1)
|
||||
addView(overflowMenuIcon)
|
||||
@@ -147,15 +153,16 @@ class ToolbarView : LinearLayout {
|
||||
}
|
||||
TooltipCompat.setTooltipText(imageView, action.title)
|
||||
|
||||
val submenu = if (action.subActions.isEmpty()) null else PopupMenu(context, imageView).apply {
|
||||
for ((i, subAction) in action.subActions.withIndex()) {
|
||||
menu.add(0, i, 0, subAction.title)
|
||||
val submenu =
|
||||
if (action.subActions.isEmpty()) null else PopupMenu(context, imageView).apply {
|
||||
for ((i, subAction) in action.subActions.withIndex()) {
|
||||
menu.add(0, i, 0, subAction.title)
|
||||
}
|
||||
setOnMenuItemClickListener {
|
||||
action.subActions[it.itemId].clickAction.invoke()
|
||||
true
|
||||
}
|
||||
}
|
||||
setOnMenuItemClickListener {
|
||||
action.subActions[it.itemId].clickAction.invoke()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
imageView.setOnClickListener { _ ->
|
||||
if (submenu != null) {
|
||||
@@ -213,13 +220,12 @@ open class ToolbarSubaction(val title: String, var clickAction: (() -> Unit)) {
|
||||
|
||||
}
|
||||
|
||||
class FavoriteToolbarAction(val context: Context, val item: Searchable)
|
||||
: ToolbarAction(
|
||||
R.drawable.ic_star_outline,
|
||||
context.getString(R.string.favorites_menu_pin)
|
||||
class FavoriteToolbarAction(val context: Context, val item: Searchable) : ToolbarAction(
|
||||
R.drawable.ic_star_outline,
|
||||
context.getString(R.string.favorites_menu_pin)
|
||||
) {
|
||||
|
||||
private val viewModel = ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java]
|
||||
private val viewModel: FavoritesViewModel by (context as AppCompatActivity).viewModel()
|
||||
private val isPinned = viewModel.isPinned(item)
|
||||
|
||||
init {
|
||||
@@ -243,13 +249,12 @@ class FavoriteToolbarAction(val context: Context, val item: Searchable)
|
||||
}
|
||||
}
|
||||
|
||||
class VisibilityToolbarAction(val context: Context, val item: Searchable)
|
||||
: ToolbarAction(
|
||||
R.drawable.ic_visibility,
|
||||
context.getString(R.string.menu_hide)
|
||||
class VisibilityToolbarAction(val context: Context, val item: Searchable) : ToolbarAction(
|
||||
R.drawable.ic_visibility,
|
||||
context.getString(R.string.menu_hide)
|
||||
) {
|
||||
|
||||
private val viewModel = ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java]
|
||||
private val viewModel: FavoritesViewModel by (context as AppCompatActivity).viewModel()
|
||||
private val isHidden = viewModel.isHidden(item)
|
||||
|
||||
init {
|
||||
|
||||
@@ -23,6 +23,7 @@ import de.mm20.launcher2.search.data.MissingPermission
|
||||
import de.mm20.launcher2.search.data.Searchable
|
||||
import de.mm20.launcher2.ui.R
|
||||
import kotlinx.android.synthetic.main.view_calendar_widget.view.*
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
@@ -119,8 +120,8 @@ class CalendarWidget : LauncherWidget {
|
||||
selectedDay = availableDays[i - 1]
|
||||
}
|
||||
|
||||
val viewModel = ViewModelProvider(context as AppCompatActivity)[CalendarViewModel::class.java]
|
||||
val favViewModel = ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java]
|
||||
val viewModel: CalendarViewModel by (context as AppCompatActivity).viewModel()
|
||||
val favViewModel: FavoritesViewModel by (context as AppCompatActivity).viewModel()
|
||||
calendarEvents = viewModel.upcomingCalendarEvents
|
||||
pinnedCalendarEvents = favViewModel.pinnedCalendarEvents
|
||||
|
||||
|
||||
@@ -22,11 +22,13 @@ import de.mm20.launcher2.ktx.dp
|
||||
import de.mm20.launcher2.legacy.helper.ActivityStarter
|
||||
import de.mm20.launcher2.music.MusicViewModel
|
||||
import de.mm20.launcher2.music.PlaybackState
|
||||
import de.mm20.launcher2.search.SearchViewModel
|
||||
import de.mm20.launcher2.ui.LegacyLauncherTheme
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.widget.MusicWidget
|
||||
import de.mm20.launcher2.ui.widget.WeatherWidget
|
||||
import kotlinx.android.synthetic.main.compact_music.view.*
|
||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||
|
||||
class MusicWidget : LauncherWidget {
|
||||
|
||||
@@ -44,7 +46,7 @@ class MusicWidget : LauncherWidget {
|
||||
override val name: String
|
||||
get() = context.getString(R.string.widget_name_music)
|
||||
|
||||
private val viewModel = ViewModelProvider(context as AppCompatActivity)[MusicViewModel::class.java]
|
||||
private val viewModel: MusicViewModel by (context as AppCompatActivity).viewModel()
|
||||
|
||||
constructor(context: Context) : super(context)
|
||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
||||
@@ -79,7 +81,7 @@ class MusicWidget : LauncherWidget {
|
||||
class MusicCompactView : FrameLayout, CompactView {
|
||||
|
||||
|
||||
private val viewModel = ViewModelProvider(context as AppCompatActivity)[MusicViewModel::class.java]
|
||||
private val viewModel: MusicViewModel by (context as AppCompatActivity).viewModel()
|
||||
|
||||
override fun setTranslucent(translucent: Boolean) {
|
||||
if (translucent) {
|
||||
|
||||
@@ -217,63 +217,3 @@ class DateCompactView : TextClock, CompactView {
|
||||
}
|
||||
}
|
||||
|
||||
class RecommendedAppsCompactView @JvmOverloads constructor(
|
||||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyleAttr), CompactView {
|
||||
|
||||
val viewModel = ViewModelProvider(context as AppCompatActivity)[FavoritesViewModel::class.java]
|
||||
val items = viewModel.getTopFavorites(4)
|
||||
|
||||
init {
|
||||
clipChildren = false
|
||||
clipToPadding = false
|
||||
layoutTransition = LayoutTransition()
|
||||
items.observe(context as LifecycleOwner, Observer {
|
||||
removeAllViews()
|
||||
for (s in it) {
|
||||
val searchableView = LauncherIconView(context)
|
||||
searchableView.icon = s.getPlaceholderIcon(context)
|
||||
lifecycleScope.launch {
|
||||
IconRepository.getInstance(context).getIcon(s, (48 * dp).toInt()).collect {
|
||||
searchableView.icon = it
|
||||
}
|
||||
}
|
||||
val frameLayout = FrameLayout(context)
|
||||
frameLayout.clipChildren = false
|
||||
frameLayout.clipToPadding = false
|
||||
searchableView.layoutParams = FrameLayout.LayoutParams(
|
||||
(48 * dp).toInt(),
|
||||
(48 * dp).toInt()
|
||||
).also {
|
||||
it.gravity = Gravity.CENTER
|
||||
}
|
||||
searchableView.badge = BadgeProvider.getInstance(context).getLiveBadge(s.badgeKey)
|
||||
searchableView.elevation = 2 * dp
|
||||
searchableView.setOnClickListener {
|
||||
if(!ActivityStarter.start(context, searchableView, s)) {
|
||||
searchableView.performLongClick()
|
||||
}
|
||||
}
|
||||
searchableView.setOnLongClickListener {
|
||||
SearchableBottomSheet(s).show((context as AppCompatActivity).supportFragmentManager, null)
|
||||
return@setOnLongClickListener true
|
||||
}
|
||||
frameLayout.addView(searchableView)
|
||||
frameLayout.layoutParams = LayoutParams(
|
||||
0,
|
||||
(48 * dp).toInt()
|
||||
).also {
|
||||
it.weight = 1f
|
||||
}
|
||||
addView(frameLayout)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun setTranslucent(translucent: Boolean) {
|
||||
|
||||
}
|
||||
|
||||
override var goToParent: (() -> Unit)? = null
|
||||
|
||||
}
|
||||
@@ -7,10 +7,12 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.applications.AppViewModel
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
|
||||
@Composable
|
||||
fun applicationResults(): LazyListScope.(listState: LazyListState) -> Unit {
|
||||
val apps by viewModel<AppViewModel>().applications.observeAsState(emptyList())
|
||||
val viewModel: AppViewModel = getViewModel()
|
||||
val apps by viewModel.applications.observeAsState(emptyList())
|
||||
return {
|
||||
SearchableGrid(items = apps, listState = it)
|
||||
}
|
||||
|
||||
@@ -16,10 +16,12 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.calculator.CalculatorViewModel
|
||||
import de.mm20.launcher2.ui.component.SectionDivider
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
|
||||
@Composable
|
||||
fun calculatorItem(): LazyListScope.() -> Unit {
|
||||
val calculator by viewModel<CalculatorViewModel>().calculator.observeAsState()
|
||||
val viewModel: CalculatorViewModel = getViewModel()
|
||||
val calculator by viewModel.calculator.observeAsState()
|
||||
return {
|
||||
calculator?.let {
|
||||
item {
|
||||
|
||||
@@ -7,10 +7,13 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.favorites.FavoritesViewModel
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
|
||||
@Composable
|
||||
fun favoriteResults(): LazyListScope.(listState: LazyListState) -> Unit {
|
||||
val favorites by viewModel<FavoritesViewModel>().getFavorites(5).observeAsState(emptyList())
|
||||
val viewModel: FavoritesViewModel = getViewModel()
|
||||
|
||||
val favorites by viewModel.getFavorites(5).observeAsState(emptyList())
|
||||
return {
|
||||
SearchableGrid(items = favorites, listState = it)
|
||||
}
|
||||
|
||||
@@ -6,10 +6,12 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.files.FilesViewModel
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
|
||||
@Composable
|
||||
fun fileResults(): LazyListScope.() -> Unit {
|
||||
val files by viewModel<FilesViewModel>().files.observeAsState(emptyList())
|
||||
val viewModel: FilesViewModel = getViewModel()
|
||||
val files by viewModel.files.observeAsState(emptyList())
|
||||
return {
|
||||
files?.let { SearchableList(items = it) }
|
||||
}
|
||||
|
||||
@@ -6,13 +6,13 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.ui.component.SectionDivider
|
||||
import de.mm20.launcher2.wikipedia.WikipediaViewModel
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
|
||||
@Composable
|
||||
fun wikipediaResult(): LazyListScope.() -> Unit {
|
||||
val viewModel = viewModel<WikipediaViewModel>()
|
||||
val viewModel: WikipediaViewModel = getViewModel()
|
||||
val wikipedia by viewModel.wikipedia.observeAsState()
|
||||
return {
|
||||
wikipedia?.let {
|
||||
|
||||
@@ -28,6 +28,7 @@ import de.mm20.launcher2.ui.LauncherTheme
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.pluralResource
|
||||
import de.mm20.launcher2.ui.searchable.DeprecatedSearchableList
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
@@ -35,7 +36,7 @@ import kotlin.math.min
|
||||
@Composable
|
||||
fun CalendarWidget() {
|
||||
|
||||
val viewModel: CalendarViewModel = viewModel()
|
||||
val viewModel: CalendarViewModel = getViewModel()
|
||||
val favViewModel: FavoritesViewModel = viewModel()
|
||||
|
||||
val events by viewModel.upcomingCalendarEvents.observeAsState()
|
||||
|
||||
@@ -21,18 +21,16 @@ import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import de.mm20.launcher2.music.MusicViewModel
|
||||
import de.mm20.launcher2.music.PlaybackState
|
||||
import de.mm20.launcher2.ui.R
|
||||
import de.mm20.launcher2.ui.ktx.conditional
|
||||
import de.mm20.launcher2.ui.locals.LocalColorScheme
|
||||
import de.mm20.launcher2.ui.orange
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
|
||||
@OptIn(
|
||||
ExperimentalFoundationApi::class, ExperimentalComposeUiApi::class,
|
||||
@@ -41,7 +39,7 @@ import de.mm20.launcher2.ui.orange
|
||||
@Composable
|
||||
fun MusicWidget() {
|
||||
|
||||
val viewModel: MusicViewModel = viewModel()
|
||||
val viewModel: MusicViewModel = getViewModel()
|
||||
|
||||
val albumArt by viewModel.albumArt.observeAsState()
|
||||
val title by viewModel.title.observeAsState()
|
||||
|
||||
Reference in New Issue
Block a user