mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-1179 Widgets | Enhancement | Save selected view in widget with set between app launches (#3154)
This commit is contained in:
parent
8efc6b4c8a
commit
c58149f102
8 changed files with 84 additions and 19 deletions
|
@ -2,7 +2,9 @@ package com.anytypeio.anytype.core_models
|
|||
|
||||
/**
|
||||
* @property [collapsed] list of collapsed widgets
|
||||
* @property [widgetsToActiveViews] maps specific widget to the selected view inside this widget
|
||||
*/
|
||||
data class WidgetSession(
|
||||
val collapsed: List<Id>
|
||||
val collapsed: List<Id> = emptyList(),
|
||||
val widgetsToActiveViews: Map<Id, Id> = emptyMap()
|
||||
)
|
|
@ -13,6 +13,7 @@ dependencies {
|
|||
implementation libs.coroutinesAndroid
|
||||
implementation libs.gson
|
||||
implementation libs.lifecycleLiveData
|
||||
implementation libs.kotlinxSerializationJson
|
||||
|
||||
implementation libs.room
|
||||
implementation libs.roomKtx
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package com.anytypeio.anytype.persistence.common
|
||||
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import timber.log.Timber
|
||||
|
||||
typealias JsonString = String
|
||||
|
||||
fun Map<String, String>.toJsonString(): JsonString = try {
|
||||
JsonObject(
|
||||
content = mapValues { entry ->
|
||||
JsonPrimitive(entry.value)
|
||||
}
|
||||
).toString()
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error while mapping to json string")
|
||||
""
|
||||
}
|
||||
|
||||
fun JsonString.toStringMap(): Map<String, String> = try {
|
||||
if (this.isNotEmpty()) {
|
||||
Json.decodeFromString(this)
|
||||
} else {
|
||||
emptyMap()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Error while mapping from json string")
|
||||
emptyMap()
|
||||
}
|
|
@ -5,6 +5,8 @@ import com.anytypeio.anytype.core_models.ThemeMode
|
|||
import com.anytypeio.anytype.core_models.Wallpaper
|
||||
import com.anytypeio.anytype.core_models.WidgetSession
|
||||
import com.anytypeio.anytype.data.auth.repo.UserSettingsCache
|
||||
import com.anytypeio.anytype.persistence.common.toJsonString
|
||||
import com.anytypeio.anytype.persistence.common.toStringMap
|
||||
|
||||
class DefaultUserSettingsCache(private val prefs: SharedPreferences) : UserSettingsCache {
|
||||
|
||||
|
@ -57,7 +59,7 @@ class DefaultUserSettingsCache(private val prefs: SharedPreferences) : UserSetti
|
|||
val type = prefs.getInt(WALLPAPER_TYPE_KEY, -1)
|
||||
if (type != -1) {
|
||||
val value = prefs.getString(WALLPAPER_VALUE_KEY, null)
|
||||
if (value != null && value.isNotEmpty()) {
|
||||
if (!value.isNullOrEmpty()) {
|
||||
return when (type) {
|
||||
WALLPAPER_TYPE_COLOR -> {
|
||||
Wallpaper.Color(value)
|
||||
|
@ -68,6 +70,7 @@ class DefaultUserSettingsCache(private val prefs: SharedPreferences) : UserSetti
|
|||
WALLPAPER_TYPE_IMAGE -> {
|
||||
Wallpaper.Image(value)
|
||||
}
|
||||
|
||||
else -> {
|
||||
Wallpaper.Default
|
||||
}
|
||||
|
@ -122,23 +125,26 @@ class DefaultUserSettingsCache(private val prefs: SharedPreferences) : UserSetti
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getWidgetSession(): WidgetSession {
|
||||
return if (prefs.contains(COLLAPSED_WIDGETS_KEY)) {
|
||||
WidgetSession(
|
||||
collapsed = prefs.getStringSet(COLLAPSED_WIDGETS_KEY, emptySet())
|
||||
.orEmpty()
|
||||
.toList()
|
||||
)
|
||||
} else
|
||||
WidgetSession(
|
||||
collapsed = emptyList()
|
||||
)
|
||||
}
|
||||
override suspend fun getWidgetSession(): WidgetSession = WidgetSession(
|
||||
collapsed = if (prefs.contains(COLLAPSED_WIDGETS_KEY)) {
|
||||
prefs.getStringSet(COLLAPSED_WIDGETS_KEY, emptySet())
|
||||
.orEmpty()
|
||||
.toList()
|
||||
} else {
|
||||
emptyList()
|
||||
},
|
||||
widgetsToActiveViews = if (prefs.contains(ACTIVE_WIDGETS_VIEWS_KEY)) {
|
||||
prefs.getString(ACTIVE_WIDGETS_VIEWS_KEY, "")!!.toStringMap()
|
||||
} else {
|
||||
emptyMap()
|
||||
}
|
||||
)
|
||||
|
||||
override suspend fun saveWidgetSession(session: WidgetSession) {
|
||||
prefs
|
||||
.edit()
|
||||
.putStringSet(COLLAPSED_WIDGETS_KEY, session.collapsed.toSet())
|
||||
.putString(ACTIVE_WIDGETS_VIEWS_KEY, session.widgetsToActiveViews.toJsonString())
|
||||
.apply()
|
||||
}
|
||||
|
||||
|
@ -167,5 +173,6 @@ class DefaultUserSettingsCache(private val prefs: SharedPreferences) : UserSetti
|
|||
const val THEME_TYPE_NIGHT = 3
|
||||
|
||||
const val COLLAPSED_WIDGETS_KEY = "prefs.user_settings.collapsed-widgets"
|
||||
const val ACTIVE_WIDGETS_VIEWS_KEY = "prefs.user_settings.active-widget-views"
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.anytypeio.anytype
|
||||
package com.anytypeio.anytype.persistence
|
||||
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import androidx.room.Room
|
||||
|
@ -6,6 +6,8 @@ import androidx.test.platform.app.InstrumentationRegistry
|
|||
import com.anytypeio.anytype.persistence.db.AnytypeDatabase
|
||||
import com.anytypeio.anytype.persistence.model.AccountTable
|
||||
import com.anytypeio.anytype.test_utils.MockDataFactory
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.After
|
||||
|
@ -14,8 +16,6 @@ import org.junit.Test
|
|||
import org.junit.runner.RunWith
|
||||
import org.robolectric.RobolectricTestRunner
|
||||
import org.robolectric.annotation.Config
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
@Config(manifest = Config.NONE)
|
|
@ -66,6 +66,7 @@ import com.anytypeio.anytype.presentation.widgets.WidgetDispatchEvent
|
|||
import com.anytypeio.anytype.presentation.widgets.WidgetSessionStateHolder
|
||||
import com.anytypeio.anytype.presentation.widgets.WidgetView
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.Subscription
|
||||
import com.anytypeio.anytype.presentation.widgets.getActiveTabViews
|
||||
import com.anytypeio.anytype.presentation.widgets.parseWidgets
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
|
@ -305,7 +306,10 @@ class HomeScreenViewModel(
|
|||
viewModelScope.launch {
|
||||
saveWidgetSession.execute(
|
||||
SaveWidgetSession.Params(
|
||||
WidgetSession(collapsed = collapsedWidgetStateHolder.get())
|
||||
WidgetSession(
|
||||
collapsed = collapsedWidgetStateHolder.get(),
|
||||
widgetsToActiveViews = views.value.getActiveTabViews()
|
||||
)
|
||||
)
|
||||
)
|
||||
val subscriptions = widgets.value.orEmpty().map { widget ->
|
||||
|
@ -718,8 +722,9 @@ class HomeScreenViewModel(
|
|||
val session = withContext(appCoroutineDispatchers.io) {
|
||||
getWidgetSession.execute(Unit).getOrNull()
|
||||
}
|
||||
if (session != null && session.collapsed.isNotEmpty()) {
|
||||
if (session != null) {
|
||||
collapsedWidgetStateHolder.set(session.collapsed)
|
||||
widgetActiveViewStateHolder.init(session.widgetsToActiveViews)
|
||||
}
|
||||
proceedWithOpeningWidgetObject(widgetObject = configStorage.get().widgets)
|
||||
}
|
||||
|
|
|
@ -8,12 +8,17 @@ import kotlinx.coroutines.flow.mapLatest
|
|||
|
||||
interface WidgetActiveViewStateHolder {
|
||||
|
||||
fun init(map: WidgetToActiveView)
|
||||
fun onChangeCurrentWidgetView(widget: Id, view: Id)
|
||||
fun observeCurrentWidgetView(widget: Id): Flow<Id?>
|
||||
|
||||
class Impl @Inject constructor() : WidgetActiveViewStateHolder {
|
||||
private val widgetToActiveView = MutableStateFlow<WidgetToActiveView>(mapOf())
|
||||
|
||||
override fun init(map: WidgetToActiveView) {
|
||||
widgetToActiveView.value = map
|
||||
}
|
||||
|
||||
override fun onChangeCurrentWidgetView(widget: Id, view: Id) {
|
||||
widgetToActiveView.value = widgetToActiveView.value + mapOf(widget to view)
|
||||
}
|
||||
|
|
|
@ -149,4 +149,18 @@ fun ObjectWrapper.Basic.widgetElementIcon(builder: UrlBuilder) : ObjectIcon {
|
|||
}
|
||||
else -> ObjectIcon.None
|
||||
}
|
||||
}
|
||||
|
||||
fun List<WidgetView>.getActiveTabViews() : Map<Id, Id> {
|
||||
return filterIsInstance<WidgetView.SetOfObjects>().mapNotNull { widget ->
|
||||
if (widget.tabs.isNotEmpty()) {
|
||||
val selected = widget.tabs.firstOrNull { it.isSelected }
|
||||
if (selected != null)
|
||||
widget.id to selected.id
|
||||
else
|
||||
null
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}.toMap()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue