Migrate grid column count preference

This commit is contained in:
MM20 2022-01-25 21:21:46 +01:00
parent 8799c15682
commit b01f9d3f4d
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
8 changed files with 149 additions and 94 deletions

View File

@ -4,6 +4,7 @@ import android.content.Context
import de.mm20.launcher2.database.AppDatabase import de.mm20.launcher2.database.AppDatabase
import de.mm20.launcher2.database.entities.FavoritesItemEntity import de.mm20.launcher2.database.entities.FavoritesItemEntity
import de.mm20.launcher2.ktx.ceilToInt import de.mm20.launcher2.ktx.ceilToInt
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.search.SearchableDeserializer import de.mm20.launcher2.search.SearchableDeserializer
import de.mm20.launcher2.search.data.CalendarEvent import de.mm20.launcher2.search.data.CalendarEvent
@ -33,7 +34,8 @@ interface FavoritesRepository {
internal class FavoritesRepositoryImpl( internal class FavoritesRepositoryImpl(
private val context: Context, private val context: Context,
private val database: AppDatabase private val database: AppDatabase,
private val dataStore: LauncherDataStore
) : FavoritesRepository, KoinComponent { ) : FavoritesRepository, KoinComponent {
private val scope = CoroutineScope(Job() + Dispatchers.Default) private val scope = CoroutineScope(Job() + Dispatchers.Default)
@ -42,16 +44,7 @@ internal class FavoritesRepositoryImpl(
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val gridColumns = callbackFlow { val gridColumns = dataStore.data.map { it.grid.columnCount }.distinctUntilChanged()
send(LauncherPreferences.instance.gridColumnCount)
val unregister =
LauncherPreferences.instance.doOnPreferenceChange("grid_column_count") {
trySendBlocking(LauncherPreferences.instance.gridColumnCount)
}
awaitClose {
unregister()
}
}
val dao = database.searchDao() val dao = database.searchDao()
val pinnedFavorites = dao.getFavorites().map { val pinnedFavorites = dao.getFavorites().map {

View File

@ -91,5 +91,5 @@ val favoritesModule = module {
return@factory NullDeserializer() return@factory NullDeserializer()
} }
single<FavoritesRepository> { FavoritesRepositoryImpl(androidContext(), get()) } single<FavoritesRepository> { FavoritesRepositoryImpl(androidContext(), get(), get()) }
} }

View File

@ -4,38 +4,45 @@ import android.content.Context
fun createFactorySettings(context: Context): Settings { fun createFactorySettings(context: Context): Settings {
return Settings.newBuilder() return Settings.newBuilder()
.setAppearance(Settings.AppearanceSettings .setAppearance(
Settings.AppearanceSettings
.newBuilder() .newBuilder()
.setTheme(Settings.AppearanceSettings.Theme.System) .setTheme(Settings.AppearanceSettings.Theme.System)
.setColorScheme(Settings.AppearanceSettings.ColorScheme.Default) .setColorScheme(Settings.AppearanceSettings.ColorScheme.Default)
.build() .build()
) )
.setWeather(Settings.WeatherSettings .setWeather(
Settings.WeatherSettings
.newBuilder() .newBuilder()
.setProvider(Settings.WeatherSettings.WeatherProvider.MetNo) .setProvider(Settings.WeatherSettings.WeatherProvider.MetNo)
.setImperialUnits(context.resources.getBoolean(R.bool.default_imperialUnits)) .setImperialUnits(context.resources.getBoolean(R.bool.default_imperialUnits))
.build() .build()
) )
.setMusicWidget(Settings.MusicWidgetSettings .setMusicWidget(
Settings.MusicWidgetSettings
.newBuilder() .newBuilder()
.setFilterSources(true) .setFilterSources(true)
.build() .build()
) )
.setCalendarWidget(Settings.CalendarWidgetSettings .setCalendarWidget(
Settings.CalendarWidgetSettings
.newBuilder() .newBuilder()
.setHideAlldayEvents(false) .setHideAlldayEvents(false)
) )
.setClockWidget(Settings.ClockWidgetSettings .setClockWidget(
Settings.ClockWidgetSettings
.newBuilder() .newBuilder()
.setLayout(Settings.ClockWidgetSettings.ClockWidgetLayout.Vertical) .setLayout(Settings.ClockWidgetSettings.ClockWidgetLayout.Vertical)
.setClockStyle(Settings.ClockWidgetSettings.ClockStyle.DigitalClock1) .setClockStyle(Settings.ClockWidgetSettings.ClockStyle.DigitalClock1)
.build() .build()
) )
.setFavorites(Settings.FavoritesSettings .setFavorites(
Settings.FavoritesSettings
.newBuilder() .newBuilder()
.setEnabled(true) .setEnabled(true)
) )
.setFileSearch(Settings.FilesSearchSettings .setFileSearch(
Settings.FilesSearchSettings
.newBuilder() .newBuilder()
.setLocalFiles(true) .setLocalFiles(true)
.setNextcloud(false) .setNextcloud(false)
@ -43,42 +50,55 @@ fun createFactorySettings(context: Context): Settings {
.setOnedrive(false) .setOnedrive(false)
.setNextcloud(false) .setNextcloud(false)
) )
.setContactsSearch(Settings.ContactsSearchSettings .setContactsSearch(
Settings.ContactsSearchSettings
.newBuilder() .newBuilder()
.setEnabled(true) .setEnabled(true)
) )
.setCalendarSearch(Settings.CalendarSearchSettings .setCalendarSearch(
Settings.CalendarSearchSettings
.newBuilder() .newBuilder()
.setEnabled(true) .setEnabled(true)
) )
.setCalculatorSearch(Settings.CalculatorSearchSettings .setCalculatorSearch(
Settings.CalculatorSearchSettings
.newBuilder() .newBuilder()
.setEnabled(true) .setEnabled(true)
) )
.setUnitConverterSearch(Settings.UnitConverterSearchSettings .setUnitConverterSearch(
Settings.UnitConverterSearchSettings
.newBuilder() .newBuilder()
.setEnabled(true) .setEnabled(true)
) )
.setWikipediaSearch(Settings.WikipediaSearchSettings .setWikipediaSearch(
Settings.WikipediaSearchSettings
.newBuilder() .newBuilder()
.setEnabled(false) .setEnabled(false)
.setImages(false) .setImages(false)
.setCustomUrl("") .setCustomUrl("")
) )
.setWebsiteSearch(Settings.WebsiteSearchSettings .setWebsiteSearch(
Settings.WebsiteSearchSettings
.newBuilder() .newBuilder()
.setEnabled(false) .setEnabled(false)
) )
.setWebSearch(Settings.WebSearchSettings .setWebSearch(
Settings.WebSearchSettings
.newBuilder() .newBuilder()
.setEnabled(true) .setEnabled(true)
) )
.setBadges(Settings.BadgeSettings .setBadges(
Settings.BadgeSettings
.newBuilder() .newBuilder()
.setNotifications(true) .setNotifications(true)
.setCloudFiles(true) .setCloudFiles(true)
.setShortcuts(true) .setShortcuts(true)
.setSuspendedApps(true) .setSuspendedApps(true)
) )
.setGrid(
Settings.GridSettings.newBuilder()
.setColumnCount(context.resources.getInteger(R.integer.config_columnCount))
.build()
)
.build() .build()
} }

View File

@ -74,19 +74,6 @@ class LauncherPreferences(val context: Application, version: Int = 3) {
var easterEggEnabled by BooleanPreference("easter_egg", default = false) var easterEggEnabled by BooleanPreference("easter_egg", default = false)
var gridColumnCount by IntPreference("grid_column_count", default = context.resources.getInteger(R.integer.config_columnCount))
fun doOnPreferenceChange(vararg keys: String, action: (String) -> Unit): () -> Unit {
val listener = { _: SharedPreferences, key: String ->
if (keys.contains(key)) action(key)
}
preferences.registerOnSharedPreferenceChangeListener(listener)
return {
preferences.unregisterOnSharedPreferenceChangeListener(listener)
}
}
companion object { companion object {
lateinit var instance: LauncherPreferences lateinit var instance: LauncherPreferences
fun initialize(app: Application) { fun initialize(app: Application) {

View File

@ -117,4 +117,9 @@ message Settings {
} }
BadgeSettings badges = 18; BadgeSettings badges = 18;
message GridSettings {
uint32 column_count = 1;
}
GridSettings grid = 19;
} }

View File

@ -6,36 +6,61 @@ import android.util.AttributeSet
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.view.children import androidx.core.view.children
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListUpdateCallback import androidx.recyclerview.widget.ListUpdateCallback
import de.mm20.launcher2.ktx.ceilToInt import de.mm20.launcher2.ktx.ceilToInt
import de.mm20.launcher2.ktx.lifecycleOwner
import de.mm20.launcher2.ktx.lifecycleScope import de.mm20.launcher2.ktx.lifecycleScope
import de.mm20.launcher2.legacy.helper.ActivityStarter import de.mm20.launcher2.legacy.helper.ActivityStarter
import de.mm20.launcher2.legacy.helper.ActivityStarterCallback import de.mm20.launcher2.legacy.helper.ActivityStarterCallback
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.search.data.Searchable import de.mm20.launcher2.search.data.Searchable
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.legacy.searchable.SearchableView import de.mm20.launcher2.ui.legacy.searchable.SearchableView
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.*
import kotlinx.coroutines.ObsoleteCoroutinesApi
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.actor import kotlinx.coroutines.channels.actor
import kotlinx.coroutines.launch import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.withContext import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
import java.util.* import java.util.*
import kotlin.math.min import kotlin.math.min
class SearchGridView : ViewGroup, ActivityStarterCallback { class SearchGridView : ViewGroup, ActivityStarterCallback, KoinComponent {
override fun onResume() { override fun onResume() {
while (postponedDiffs.isNotEmpty()) { while (postponedDiffs.isNotEmpty()) {
postponedDiffs.poll()?.let { applyDiff(it, true) } postponedDiffs.poll()?.let { applyDiff(it, true) }
} }
} }
val dataStore: LauncherDataStore by inject()
var job: Job? = null
override fun onAttachedToWindow() {
super.onAttachedToWindow()
job?.cancel()
lifecycleScope.launch {
lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
dataStore.data.map { it.grid.columnCount }.distinctUntilChanged().collectLatest {
columnCount = it
}
}
}
}
var columnCount: Int = 1 var columnCount: Int = 1
set(value) { set(value) {
if (value > 0) field = value if (value > 0) {
field = value
requestLayout()
}
else throw IllegalArgumentException("columnCount must be positive (is $value)") else throw IllegalArgumentException("columnCount must be positive (is $value)")
} }
@ -100,8 +125,9 @@ class SearchGridView : ViewGroup, ActivityStarterCallback {
} }
init { init {
columnCount = LauncherPreferences.instance.gridColumnCount.takeIf { it > 1 } columnCount = runBlocking {
?: context.resources.getInteger(R.integer.config_columnCount) dataStore.data.map { it.grid.columnCount }.first().takeIf { it > 0 } ?: 5
}
} }
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

View File

@ -45,6 +45,19 @@ fun AppearanceSettingsScreen() {
} }
) )
} }
PreferenceCategory(title = stringResource(R.string.preference_category_grid)) {
val columnCount by viewModel.columnCount.observeAsState()
ListPreference(
title = stringResource(R.string.preference_grid_column_count),
items = (3..8).map {
it.toString() to it
},
value = columnCount,
onValueChanged = {
if (it != null) viewModel.setColumnCount(it)
}
)
}
} }
} }
} }

View File

@ -35,4 +35,15 @@ class AppearanceSettingsScreenVM : ViewModel(), KoinComponent {
} }
} }
} }
val columnCount = dataStore.data.map { it.grid.columnCount }.asLiveData()
fun setColumnCount(columnCount: Int) {
viewModelScope.launch {
dataStore.updateData {
it.toBuilder()
.setGrid(it.grid.toBuilder().setColumnCount(columnCount))
.build()
}
}
}
} }