mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
Dashboard | Object icon refactoring (#1673)
This commit is contained in:
parent
c15d2485c8
commit
c3fab7349b
22 changed files with 314 additions and 212 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -3,6 +3,7 @@
|
|||
/local.properties
|
||||
/configuration.properties
|
||||
/github.properties
|
||||
/apikeys.properties
|
||||
.idea/*
|
||||
!.idea/copyright
|
||||
.DS_Store
|
||||
|
@ -11,4 +12,4 @@
|
|||
/captures
|
||||
.externalNativeBuild
|
||||
ktlint
|
||||
.idea/*.xml
|
||||
.idea/*.xml
|
||||
|
|
|
@ -21,6 +21,8 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
|||
import com.anytypeio.anytype.domain.config.Gateway
|
||||
import com.anytypeio.anytype.domain.dataview.interactor.ObjectRelationList
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.relations.AddToFeaturedRelations
|
||||
import com.anytypeio.anytype.domain.relations.RemoveFromFeaturedRelations
|
||||
import com.anytypeio.anytype.mocking.MockDataFactory
|
||||
import com.anytypeio.anytype.presentation.page.Editor
|
||||
import com.anytypeio.anytype.presentation.page.editor.DetailModificationManager
|
||||
|
@ -64,6 +66,8 @@ class ObjectRelationListTest {
|
|||
|
||||
private lateinit var objectRelationList: ObjectRelationList
|
||||
private lateinit var updateDetail: UpdateDetail
|
||||
private lateinit var addToFeaturedRelations: AddToFeaturedRelations
|
||||
private lateinit var removeFromFeaturedRelations: RemoveFromFeaturedRelations
|
||||
|
||||
private val ctx = MockDataFactory.randomUuid()
|
||||
private val storage = Editor.Storage()
|
||||
|
@ -76,13 +80,17 @@ class ObjectRelationListTest {
|
|||
urlBuilder = UrlBuilder(gateway)
|
||||
objectRelationList = ObjectRelationList(repo)
|
||||
updateDetail = UpdateDetail(repo)
|
||||
addToFeaturedRelations = AddToFeaturedRelations(repo)
|
||||
removeFromFeaturedRelations = RemoveFromFeaturedRelations(repo)
|
||||
TestRelationListFragment.testVmFactory = ObjectRelationListViewModelFactory(
|
||||
stores = storage,
|
||||
urlBuilder = urlBuilder,
|
||||
objectRelationList = objectRelationList,
|
||||
dispatcher = dispatcher,
|
||||
detailModificationManager = detailModificationManager,
|
||||
updateDetail = updateDetail
|
||||
updateDetail = updateDetail,
|
||||
addToFeaturedRelations = addToFeaturedRelations,
|
||||
removeFromFeaturedRelations = removeFromFeaturedRelations
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,8 @@ object HomeDashboardModule {
|
|||
searchRecentObjects: SearchRecentObjects,
|
||||
searchInboxObjects: SearchInboxObjects,
|
||||
searchObjectSets: SearchObjectSets,
|
||||
getFlavourConfig: GetFlavourConfig
|
||||
getFlavourConfig: GetFlavourConfig,
|
||||
urlBuilder: UrlBuilder
|
||||
): HomeDashboardViewModelFactory = HomeDashboardViewModelFactory(
|
||||
getProfile = getProfile,
|
||||
openDashboard = openDashboard,
|
||||
|
@ -76,7 +77,8 @@ object HomeDashboardModule {
|
|||
searchInboxObjects = searchInboxObjects,
|
||||
searchObjectSets = searchObjectSets,
|
||||
analytics = analytics,
|
||||
getFlavourConfig = getFlavourConfig
|
||||
getFlavourConfig = getFlavourConfig,
|
||||
urlBuilder = urlBuilder
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
|
|
@ -15,10 +15,8 @@ import com.anytypeio.anytype.core_utils.ext.invisible
|
|||
import com.anytypeio.anytype.core_utils.ext.shift
|
||||
import com.anytypeio.anytype.core_utils.ext.typeOf
|
||||
import com.anytypeio.anytype.core_utils.ext.visible
|
||||
import com.anytypeio.anytype.emojifier.Emojifier
|
||||
import com.anytypeio.anytype.presentation.`object`.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.desktop.DashboardView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.facebook.shimmer.ShimmerFrameLayout
|
||||
import kotlinx.android.synthetic.main.item_dashboard_card_default.view.*
|
||||
import kotlinx.android.synthetic.main.item_desktop_archive.view.*
|
||||
|
@ -137,8 +135,7 @@ class DashboardAdapter(
|
|||
with(holder) {
|
||||
bindTitle(item.title)
|
||||
bindSubtitle(item.typeName)
|
||||
bindEmoji(item.emoji)
|
||||
bindImage(item.image, item.layout, item.title)
|
||||
bindIcon(item.icon)
|
||||
bindLoading(item.isLoading)
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +156,7 @@ class DashboardAdapter(
|
|||
with(holder) {
|
||||
val item = data[position] as DashboardView.ObjectSet
|
||||
bindTitle(item.title)
|
||||
bindEmoji(item.emoji)
|
||||
bindIcon(item.icon)
|
||||
bindLoading(item.isLoading)
|
||||
}
|
||||
}
|
||||
|
@ -217,10 +214,10 @@ class DashboardAdapter(
|
|||
bindTitle(item.title)
|
||||
}
|
||||
if (payload.emojiChanged()) {
|
||||
bindEmoji(item.emoji)
|
||||
bindIcon(item.icon)
|
||||
}
|
||||
if (payload.imageChanged()) {
|
||||
bindImage(item.image, item.layout, item.title)
|
||||
bindIcon(item.icon)
|
||||
}
|
||||
if (payload.isLoadingChanged) {
|
||||
bindLoading(item.isLoading)
|
||||
|
@ -259,10 +256,6 @@ class DashboardAdapter(
|
|||
|
||||
private val tvTitle = itemView.title
|
||||
private val tvSubtitle = itemView.typeTitle
|
||||
private val ivEmoji = itemView.emojiIcon
|
||||
private val circleImage = itemView.circleImage
|
||||
private val rectangleImage = itemView.rectangleImage
|
||||
private val avatar = itemView.avatar
|
||||
private val shimmer = itemView.shimmer
|
||||
|
||||
fun bindTitle(title: String?) {
|
||||
|
@ -276,6 +269,10 @@ class DashboardAdapter(
|
|||
tvSubtitle.text = subtitle
|
||||
}
|
||||
|
||||
fun bindIcon(icon: ObjectIcon) {
|
||||
itemView.iconWidget.bind(icon)
|
||||
}
|
||||
|
||||
fun bindLoading(isLoading: Boolean) {
|
||||
if (isLoading) {
|
||||
tvTitle.invisible()
|
||||
|
@ -287,65 +284,6 @@ class DashboardAdapter(
|
|||
tvTitle.visible()
|
||||
}
|
||||
}
|
||||
|
||||
fun bindEmoji(emoji: String?) {
|
||||
try {
|
||||
emoji?.let { unicode ->
|
||||
Glide
|
||||
.with(ivEmoji)
|
||||
.load(Emojifier.uri(unicode))
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
.into(ivEmoji)
|
||||
} ?: run {
|
||||
ivEmoji.setImageDrawable(null)
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
Timber.e(e, "Could not set emoji icon")
|
||||
}
|
||||
}
|
||||
|
||||
fun bindImage(
|
||||
image: String?,
|
||||
layout: ObjectType.Layout?,
|
||||
name: String?
|
||||
) {
|
||||
when (layout) {
|
||||
ObjectType.Layout.BASIC -> bindRectangleImage(image)
|
||||
ObjectType.Layout.PROFILE -> {
|
||||
if (image != null) {
|
||||
avatar.invisible()
|
||||
bindCircleImage(image)
|
||||
} else {
|
||||
rectangleImage.invisible()
|
||||
avatar.visible()
|
||||
avatar.bind(name.orEmpty())
|
||||
}
|
||||
}
|
||||
else -> Timber.d("Skipping image bound")
|
||||
}
|
||||
}
|
||||
|
||||
private fun bindCircleImage(image: String?) {
|
||||
image?.let { url ->
|
||||
Glide
|
||||
.with(circleImage)
|
||||
.load(url)
|
||||
.centerInside()
|
||||
.circleCrop()
|
||||
.into(circleImage)
|
||||
} ?: run { circleImage.setImageDrawable(null) }
|
||||
}
|
||||
|
||||
private fun bindRectangleImage(image: String?) {
|
||||
Timber.d("Binding rectangle image: $image")
|
||||
image?.let { url ->
|
||||
Glide
|
||||
.with(rectangleImage)
|
||||
.load(url)
|
||||
.centerCrop()
|
||||
.into(rectangleImage)
|
||||
} ?: run { rectangleImage.setImageDrawable(null) }
|
||||
}
|
||||
}
|
||||
|
||||
class DocumentWithoutIconViewHolder(parent: ViewGroup) : ViewHolder(
|
||||
|
@ -430,7 +368,6 @@ class DashboardAdapter(
|
|||
class ObjectSetHolder(itemView: View) : ViewHolder(itemView) {
|
||||
|
||||
private val tvTitle = itemView.title
|
||||
private val ivEmoji = itemView.emojiIcon
|
||||
private val shimmer = itemView.shimmer
|
||||
|
||||
fun bindLoading(isLoading: Boolean) {
|
||||
|
@ -452,18 +389,8 @@ class DashboardAdapter(
|
|||
tvTitle.text = title
|
||||
}
|
||||
|
||||
fun bindEmoji(emoji: String?) {
|
||||
try {
|
||||
emoji?.let { unicode ->
|
||||
Glide
|
||||
.with(ivEmoji)
|
||||
.load(Emojifier.uri(unicode))
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
.into(ivEmoji)
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
Timber.e(e, "Could not set emoji icon")
|
||||
}
|
||||
fun bindIcon(icon: ObjectIcon) {
|
||||
itemView.iconWidget.bind(icon)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,59 +8,18 @@
|
|||
android:background="@drawable/ripple_dashboard_card"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
<com.anytypeio.anytype.core_ui.widgets.ObjectCardIconWidget
|
||||
android:id="@+id/iconWidget"
|
||||
android:layout_width="@dimen/dashboard_object_icon_default_size"
|
||||
android:layout_height="@dimen/dashboard_object_icon_default_size"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/roundedImageContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:cardCornerRadius="2dp"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/rectangleImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/emoji"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:textColor="@color/emoji_color"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/emojiIcon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/circleImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.anytypeio.anytype.core_ui.widgets.AvatarWidget
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/circle_solid_default"
|
||||
android:visibility="invisible"
|
||||
app:text_size="28sp" />
|
||||
|
||||
</FrameLayout>
|
||||
android:layout_marginTop="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
style="@style/DashboardDocumentTitleStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:hint="@string/untitled"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="79dp"
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
android:id="@+id/tvDocTitle"
|
||||
style="@style/DashboardDocAlternativeTitleStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/untitled"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
|
|
|
@ -37,4 +37,5 @@
|
|||
<dimen name="single_option_value_bottom_list_margin">32dp</dimen>
|
||||
<dimen name="multiple_option_value_bottom_list_margin">68dp</dimen>
|
||||
<dimen name="default_dashboard_card_height">124dp</dimen>
|
||||
<dimen name="dashboard_object_icon_default_size">48dp</dimen>
|
||||
</resources>
|
|
@ -154,6 +154,7 @@
|
|||
<item name="android:ellipsize">end</item>
|
||||
<item name="android:textColor">@color/black</item>
|
||||
<item name="android:textSize">13sp</item>
|
||||
<item name="android:maxLines">3</item>
|
||||
</style>
|
||||
|
||||
<style name="DashboardDocumentSubtitleStyle">
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package com.anytypeio.anytype.core_ui.widgets
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.emojifier.Emojifier
|
||||
import com.anytypeio.anytype.presentation.`object`.ObjectIcon
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop
|
||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
|
||||
import kotlinx.android.synthetic.main.widget_object_icon_card.view.*
|
||||
import timber.log.Timber
|
||||
|
||||
class ObjectCardIconWidget @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null
|
||||
) : FrameLayout(context, attrs) {
|
||||
|
||||
private val emojiSize = resources.getDimension(R.dimen.object_icon_card_emoji_size).toInt()
|
||||
private val rectangleImageRadius = resources.getDimension(R.dimen.object_icon_card_rectangle_image_radius).toInt()
|
||||
|
||||
init {
|
||||
View.inflate(context, R.layout.widget_object_icon_card, this)
|
||||
}
|
||||
|
||||
fun bind(icon: ObjectIcon) {
|
||||
when(icon) {
|
||||
is ObjectIcon.Basic.Emoji -> {
|
||||
setBackgroundResource(R.drawable.rect_object_icon_card_emoji_background)
|
||||
ivIcon.updateLayoutParams<LayoutParams> {
|
||||
height = emojiSize
|
||||
width = emojiSize
|
||||
}
|
||||
try {
|
||||
Glide
|
||||
.with(this)
|
||||
.load(Emojifier.uri(icon.unicode))
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
.into(ivIcon)
|
||||
} catch (e: Throwable) {
|
||||
Timber.e(e, "Error while setting emoji icon for: ${icon.unicode}")
|
||||
}
|
||||
}
|
||||
is ObjectIcon.Basic.Image -> {
|
||||
setBackgroundResource(0)
|
||||
ivIcon.updateLayoutParams<LayoutParams> {
|
||||
height = LayoutParams.MATCH_PARENT
|
||||
width = LayoutParams.MATCH_PARENT
|
||||
}
|
||||
Glide
|
||||
.with(this)
|
||||
.load(icon.hash)
|
||||
.transform(
|
||||
CenterCrop(),
|
||||
RoundedCorners(rectangleImageRadius)
|
||||
)
|
||||
.into(ivIcon)
|
||||
}
|
||||
is ObjectIcon.Profile.Avatar -> {
|
||||
setBackgroundResource(R.drawable.circle_default_avatar_background)
|
||||
ivIcon.setImageDrawable(null)
|
||||
tvInitial.text = icon.name.ifEmpty { DEFAULT_INITIAL_CHAR }.first().uppercaseChar().toString()
|
||||
}
|
||||
is ObjectIcon.Profile.Image -> {
|
||||
setBackgroundResource(0)
|
||||
ivIcon.updateLayoutParams<LayoutParams> {
|
||||
height = LayoutParams.MATCH_PARENT
|
||||
width = LayoutParams.MATCH_PARENT
|
||||
}
|
||||
Glide
|
||||
.with(this)
|
||||
.load(icon.hash)
|
||||
.centerInside()
|
||||
.circleCrop()
|
||||
.into(ivIcon)
|
||||
}
|
||||
else -> {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DEFAULT_INITIAL_CHAR = "U"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="oval">
|
||||
<solid android:color="#DFDDD0" />
|
||||
</shape>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<corners android:radius="10dp" />
|
||||
<solid android:color="#F3F2EC" />
|
||||
</shape>
|
24
core-ui/src/main/res/layout/widget_object_icon_card.xml
Normal file
24
core-ui/src/main/res/layout/widget_object_icon_card.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivIcon"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:contentDescription="@string/content_description_page_icon" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvInitial"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:fontFamily="@font/inter_semibold"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="28sp"
|
||||
tools:text="U" />
|
||||
|
||||
</merge>
|
|
@ -156,5 +156,7 @@
|
|||
|
||||
<dimen name="slash_widget_item_height">55dp</dimen>
|
||||
<dimen name="data_view_divider_height">0.5dp</dimen>
|
||||
<dimen name="object_icon_card_emoji_size">28dp</dimen>
|
||||
<dimen name="object_icon_card_rectangle_image_radius">2dp</dimen>
|
||||
|
||||
</resources>
|
|
@ -3,6 +3,7 @@ package com.anytypeio.anytype.presentation.desktop
|
|||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.Url
|
||||
import com.anytypeio.anytype.presentation.`object`.ObjectIcon
|
||||
|
||||
sealed class DashboardView {
|
||||
|
||||
|
@ -29,7 +30,8 @@ sealed class DashboardView {
|
|||
val type: String? = null,
|
||||
val done: Boolean? = null,
|
||||
override val isArchived: Boolean,
|
||||
override val isLoading: Boolean = false
|
||||
override val isLoading: Boolean = false,
|
||||
val icon: ObjectIcon = ObjectIcon.None
|
||||
) : DashboardView() {
|
||||
val hasIcon = emoji != null || image != null
|
||||
}
|
||||
|
@ -46,8 +48,8 @@ sealed class DashboardView {
|
|||
override val id: Id,
|
||||
val target: Id,
|
||||
val title: String? = null,
|
||||
val emoji: String? = null,
|
||||
override val isArchived: Boolean,
|
||||
override val isLoading: Boolean = false
|
||||
override val isLoading: Boolean = false,
|
||||
val icon: ObjectIcon = ObjectIcon.None
|
||||
) : DashboardView()
|
||||
}
|
|
@ -23,8 +23,10 @@ import com.anytypeio.anytype.domain.config.GetDebugSettings
|
|||
import com.anytypeio.anytype.domain.config.GetFlavourConfig
|
||||
import com.anytypeio.anytype.domain.dashboard.interactor.*
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.page.CreatePage
|
||||
import com.anytypeio.anytype.presentation.BuildConfig
|
||||
import com.anytypeio.anytype.presentation.`object`.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.desktop.HomeDashboardStateMachine.Interactor
|
||||
import com.anytypeio.anytype.presentation.desktop.HomeDashboardStateMachine.State
|
||||
import com.anytypeio.anytype.presentation.mapper.toView
|
||||
|
@ -52,7 +54,8 @@ class HomeDashboardViewModel(
|
|||
private val searchRecentObjects: SearchRecentObjects,
|
||||
private val searchInboxObjects: SearchInboxObjects,
|
||||
private val searchObjectSets: SearchObjectSets,
|
||||
private val getFlavourConfig: GetFlavourConfig
|
||||
private val getFlavourConfig: GetFlavourConfig,
|
||||
private val urlBuilder: UrlBuilder
|
||||
) : ViewStateViewModel<State>(),
|
||||
HomeDashboardEventConverter by eventConverter,
|
||||
SupportNavigation<EventWrapper<AppNavigation.Command>> {
|
||||
|
@ -394,8 +397,9 @@ class HomeDashboardViewModel(
|
|||
archived.value = objects
|
||||
.map { ObjectWrapper.Basic(it) }
|
||||
.mapNotNull { obj ->
|
||||
val layout = obj.layout
|
||||
val oType = stateData.value?.findOTypeById(obj.type)
|
||||
if (oType?.layout == ObjectType.Layout.SET && !isDataViewEnabled.value) {
|
||||
if (layout == ObjectType.Layout.SET && !isDataViewEnabled.value) {
|
||||
null
|
||||
} else {
|
||||
DashboardView.Document(
|
||||
|
@ -409,7 +413,12 @@ class HomeDashboardViewModel(
|
|||
type = obj.type.firstOrNull(),
|
||||
typeName = oType?.name,
|
||||
layout = obj.layout,
|
||||
done = obj.done
|
||||
done = obj.done,
|
||||
icon = ObjectIcon.from(
|
||||
obj = obj,
|
||||
layout = layout,
|
||||
builder = urlBuilder
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -428,7 +437,8 @@ class HomeDashboardViewModel(
|
|||
.map { ObjectWrapper.Basic(it) }
|
||||
.mapNotNull { obj ->
|
||||
val oType = stateData.value?.findOTypeById(obj.type)
|
||||
if (oType?.layout == ObjectType.Layout.SET) {
|
||||
val layout = obj.layout
|
||||
if (layout == ObjectType.Layout.SET) {
|
||||
if (isDataViewEnabled.value) {
|
||||
DashboardView.ObjectSet(
|
||||
id = obj.id,
|
||||
|
@ -436,7 +446,11 @@ class HomeDashboardViewModel(
|
|||
title = obj.name,
|
||||
isArchived = obj.isArchived ?: false,
|
||||
isLoading = false,
|
||||
emoji = obj.iconEmoji
|
||||
icon = ObjectIcon.from(
|
||||
obj = obj,
|
||||
layout = obj.layout,
|
||||
builder = urlBuilder
|
||||
)
|
||||
)
|
||||
} else {
|
||||
null
|
||||
|
@ -453,7 +467,12 @@ class HomeDashboardViewModel(
|
|||
type = obj.type.firstOrNull(),
|
||||
typeName = oType?.name,
|
||||
layout = obj.layout,
|
||||
done = obj.done
|
||||
done = obj.done,
|
||||
icon = ObjectIcon.from(
|
||||
obj = obj,
|
||||
layout = obj.layout,
|
||||
builder = urlBuilder
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -470,8 +489,9 @@ class HomeDashboardViewModel(
|
|||
inbox.value = objects
|
||||
.map { ObjectWrapper.Basic(it) }
|
||||
.mapNotNull { obj ->
|
||||
val layout = obj.layout
|
||||
val oType = stateData.value?.findOTypeById(obj.type)
|
||||
if (oType?.layout == ObjectType.Layout.SET && !isDataViewEnabled.value) {
|
||||
if (layout == ObjectType.Layout.SET && !isDataViewEnabled.value) {
|
||||
null
|
||||
} else {
|
||||
DashboardView.Document(
|
||||
|
@ -485,7 +505,12 @@ class HomeDashboardViewModel(
|
|||
type = obj.type.firstOrNull(),
|
||||
typeName = oType?.name,
|
||||
layout = obj.layout,
|
||||
done = obj.done
|
||||
done = obj.done,
|
||||
icon = ObjectIcon.from(
|
||||
obj = obj,
|
||||
layout = obj.layout,
|
||||
builder = urlBuilder
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -506,7 +531,11 @@ class HomeDashboardViewModel(
|
|||
title = obj.name,
|
||||
isArchived = obj.isArchived ?: false,
|
||||
isLoading = false,
|
||||
emoji = obj.iconEmoji
|
||||
icon = ObjectIcon.from(
|
||||
obj = obj,
|
||||
layout = obj.layout,
|
||||
builder = urlBuilder
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.anytypeio.anytype.domain.config.GetDebugSettings
|
|||
import com.anytypeio.anytype.domain.config.GetFlavourConfig
|
||||
import com.anytypeio.anytype.domain.dashboard.interactor.*
|
||||
import com.anytypeio.anytype.domain.event.interactor.InterceptEvents
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.page.CreatePage
|
||||
|
||||
class HomeDashboardViewModelFactory(
|
||||
|
@ -27,7 +28,8 @@ class HomeDashboardViewModelFactory(
|
|||
private val searchRecentObjects: SearchRecentObjects,
|
||||
private val searchInboxObjects: SearchInboxObjects,
|
||||
private val searchObjectSets: SearchObjectSets,
|
||||
private val getFlavourConfig: GetFlavourConfig
|
||||
private val getFlavourConfig: GetFlavourConfig,
|
||||
private val urlBuilder: UrlBuilder
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -47,7 +49,8 @@ class HomeDashboardViewModelFactory(
|
|||
searchRecentObjects = searchRecentObjects,
|
||||
searchInboxObjects = searchInboxObjects,
|
||||
searchObjectSets = searchObjectSets,
|
||||
getFlavourConfig = getFlavourConfig
|
||||
getFlavourConfig = getFlavourConfig,
|
||||
urlBuilder = urlBuilder
|
||||
) as T
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
package com.anytypeio.anytype.presentation.extension
|
||||
|
||||
import com.anytypeio.anytype.core_models.Block
|
||||
import com.anytypeio.anytype.domain.`object`.ObjectWrapper
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.presentation.`object`.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.desktop.DashboardView
|
||||
|
||||
fun List<DashboardView>.addAndSortByIds(
|
||||
|
@ -44,6 +46,7 @@ fun List<DashboardView>.updateDetails(
|
|||
}
|
||||
is DashboardView.Document -> {
|
||||
if (view.target == target) {
|
||||
val obj = ObjectWrapper.Basic(details.map)
|
||||
view.copy(
|
||||
title = details.name,
|
||||
emoji = details.iconEmoji?.let { name ->
|
||||
|
@ -59,7 +62,12 @@ fun List<DashboardView>.updateDetails(
|
|||
null
|
||||
},
|
||||
isArchived = details.isArchived ?: false,
|
||||
isLoading = false
|
||||
isLoading = false,
|
||||
icon = ObjectIcon.from(
|
||||
obj = obj,
|
||||
layout = obj.layout,
|
||||
builder = builder
|
||||
)
|
||||
)
|
||||
} else {
|
||||
view
|
||||
|
@ -67,15 +75,15 @@ fun List<DashboardView>.updateDetails(
|
|||
}
|
||||
is DashboardView.ObjectSet -> {
|
||||
if (view.target == target) {
|
||||
val obj = ObjectWrapper.Basic(details.map)
|
||||
view.copy(
|
||||
title = details.name,
|
||||
emoji = details.iconEmoji?.let { name ->
|
||||
if (name.isNotEmpty())
|
||||
name
|
||||
else
|
||||
null
|
||||
},
|
||||
isArchived = details.isArchived ?: false
|
||||
isArchived = details.isArchived ?: false,
|
||||
icon = ObjectIcon.from(
|
||||
obj = obj,
|
||||
layout = obj.layout,
|
||||
builder = builder
|
||||
)
|
||||
)
|
||||
} else {
|
||||
view
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package com.anytypeio.anytype.presentation.mapper
|
||||
|
||||
import com.anytypeio.anytype.core_models.*
|
||||
import com.anytypeio.anytype.domain.`object`.ObjectWrapper
|
||||
import com.anytypeio.anytype.domain.config.DebugSettings
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.relations.Relations
|
||||
import com.anytypeio.anytype.presentation.`object`.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.desktop.DashboardView
|
||||
import com.anytypeio.anytype.presentation.navigation.ObjectView
|
||||
import com.anytypeio.anytype.presentation.page.editor.Markup
|
||||
|
@ -320,7 +322,7 @@ fun List<Block>.toDashboardViews(
|
|||
typeName = type?.name,
|
||||
layout = layout
|
||||
)
|
||||
ObjectType.Layout.SET -> content.toSetView(block.id, details)
|
||||
ObjectType.Layout.SET -> content.toSetView(block.id, details, builder)
|
||||
else -> {
|
||||
when (content.type) {
|
||||
Block.Content.Link.Type.PAGE -> content.toPageView(
|
||||
|
@ -331,7 +333,7 @@ fun List<Block>.toDashboardViews(
|
|||
typeName = type?.name,
|
||||
layout = layout
|
||||
)
|
||||
Block.Content.Link.Type.DATA_VIEW -> content.toSetView(block.id, details)
|
||||
Block.Content.Link.Type.DATA_VIEW -> content.toSetView(block.id, details, builder)
|
||||
Block.Content.Link.Type.ARCHIVE -> content.toArchiveView(block.id, details)
|
||||
else -> null
|
||||
}
|
||||
|
@ -361,36 +363,48 @@ fun Block.Content.Link.toPageView(
|
|||
typeName: String?,
|
||||
type: String?
|
||||
): DashboardView.Document {
|
||||
|
||||
val obj = ObjectWrapper.Basic(details.details[target]?.map ?: emptyMap())
|
||||
|
||||
return DashboardView.Document(
|
||||
id = id,
|
||||
target = target,
|
||||
title = details.details[target]?.name,
|
||||
emoji = details.details[target]?.iconEmoji?.let { name ->
|
||||
if (name.isNotEmpty()) name else null
|
||||
title = obj.name,
|
||||
emoji = details.details[target]?.iconEmoji?.let { unicode ->
|
||||
if (unicode.isNotEmpty()) unicode else null
|
||||
},
|
||||
image = details.details[target]?.iconImage?.let { name ->
|
||||
if (name.isNotEmpty()) builder.image(name) else null
|
||||
image = details.details[target]?.iconImage?.let { hash ->
|
||||
if (hash.isNotEmpty()) builder.image(hash) else null
|
||||
},
|
||||
isArchived = details.details[target]?.isArchived ?: false,
|
||||
isLoading = !details.details.containsKey(target),
|
||||
typeName = typeName,
|
||||
type = type,
|
||||
layout = layout,
|
||||
done = details.details[target]?.done
|
||||
done = details.details[target]?.done,
|
||||
icon = ObjectIcon.from(
|
||||
obj = obj,
|
||||
layout = layout,
|
||||
builder = builder
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun Block.Content.Link.toSetView(
|
||||
id: String,
|
||||
details: Block.Details,
|
||||
urlBuilder: UrlBuilder
|
||||
): DashboardView.ObjectSet {
|
||||
val obj = ObjectWrapper.Basic(details.details[target]?.map ?: emptyMap())
|
||||
return DashboardView.ObjectSet(
|
||||
id = id,
|
||||
target = target,
|
||||
title = details.details[target]?.name,
|
||||
emoji = details.details[target]?.iconEmoji?.let { name ->
|
||||
if (name.isNotEmpty()) name else null
|
||||
},
|
||||
icon = ObjectIcon.from(
|
||||
obj = obj,
|
||||
layout = obj.layout,
|
||||
builder = urlBuilder
|
||||
),
|
||||
isArchived = details.details[target]?.isArchived ?: false
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package com.anytypeio.anytype.presentation.`object`
|
||||
|
||||
import com.anytypeio.anytype.core_models.Hash
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.domain.`object`.ObjectWrapper
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
|
||||
sealed class ObjectIcon {
|
||||
object None : ObjectIcon()
|
||||
|
@ -9,9 +12,58 @@ sealed class ObjectIcon {
|
|||
data class Image(val hash: Hash) : Basic()
|
||||
data class Emoji(val unicode: String) : Basic()
|
||||
}
|
||||
|
||||
sealed class Profile : ObjectIcon() {
|
||||
data class Avatar(val name: String) : Profile()
|
||||
data class Image(val hash: Hash) : Profile()
|
||||
}
|
||||
|
||||
data class Task(val isChecked: Boolean) : ObjectIcon()
|
||||
|
||||
companion object {
|
||||
fun from(
|
||||
obj: ObjectWrapper.Basic,
|
||||
layout: ObjectType.Layout?,
|
||||
builder: UrlBuilder
|
||||
): ObjectIcon = when (layout) {
|
||||
ObjectType.Layout.BASIC -> {
|
||||
val img = obj.iconImage
|
||||
val emoji = obj.iconEmoji
|
||||
when {
|
||||
!img.isNullOrBlank() -> {
|
||||
Basic.Image(hash = builder.thumbnail(img))
|
||||
}
|
||||
!emoji.isNullOrBlank() -> {
|
||||
Basic.Emoji(unicode = emoji)
|
||||
}
|
||||
else -> {
|
||||
Basic.Avatar(obj.name.orEmpty())
|
||||
}
|
||||
}
|
||||
}
|
||||
ObjectType.Layout.PROFILE -> {
|
||||
val img = obj.iconImage
|
||||
if (!img.isNullOrBlank()) {
|
||||
Profile.Image(hash = builder.thumbnail(img))
|
||||
} else {
|
||||
Profile.Avatar(name = obj.name.orEmpty())
|
||||
}
|
||||
}
|
||||
ObjectType.Layout.TODO -> {
|
||||
Task(isChecked = obj.done ?: false)
|
||||
}
|
||||
ObjectType.Layout.SET -> {
|
||||
val img = obj.iconImage
|
||||
val emoji = obj.iconEmoji
|
||||
if (!img.isNullOrBlank()) {
|
||||
Basic.Image(hash = builder.thumbnail(img))
|
||||
} else if (!emoji.isNullOrBlank()) {
|
||||
Basic.Emoji(unicode = emoji)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
else -> None
|
||||
}
|
||||
}
|
||||
}
|
|
@ -74,51 +74,16 @@ class ObjectSearchViewModel(
|
|||
val targetType = listOfTypes.find { type ->
|
||||
obj.type.contains(type.url)
|
||||
}
|
||||
var icon : ObjectIcon = ObjectIcon.None
|
||||
when(targetType?.layout) {
|
||||
ObjectType.Layout.BASIC -> {
|
||||
val img = obj.iconImage
|
||||
val emoji = obj.iconEmoji
|
||||
icon = when {
|
||||
!img.isNullOrBlank() -> {
|
||||
ObjectIcon.Basic.Image(hash = urlBuilder.thumbnail(img))
|
||||
}
|
||||
!emoji.isNullOrBlank() -> {
|
||||
ObjectIcon.Basic.Emoji(unicode = emoji)
|
||||
}
|
||||
else -> {
|
||||
ObjectIcon.Basic.Avatar(obj.name.orEmpty())
|
||||
}
|
||||
}
|
||||
}
|
||||
ObjectType.Layout.PROFILE -> {
|
||||
val img = obj.iconImage
|
||||
icon = if (!img.isNullOrBlank()) {
|
||||
ObjectIcon.Profile.Image(hash = urlBuilder.thumbnail(img))
|
||||
} else {
|
||||
ObjectIcon.Profile.Avatar(name = obj.name.orEmpty())
|
||||
}
|
||||
}
|
||||
ObjectType.Layout.TODO -> {
|
||||
icon = ObjectIcon.Task(isChecked = obj.done ?: false)
|
||||
}
|
||||
ObjectType.Layout.SET -> {
|
||||
val img = obj.iconImage
|
||||
val emoji = obj.iconEmoji
|
||||
if (!img.isNullOrBlank()) {
|
||||
icon = ObjectIcon.Basic.Image(hash = urlBuilder.thumbnail(img))
|
||||
} else if (!emoji.isNullOrBlank()) {
|
||||
icon = ObjectIcon.Basic.Emoji(unicode = emoji)
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
DefaultObjectView(
|
||||
id = obj.id,
|
||||
name = obj.name.orEmpty(),
|
||||
typeName = targetType?.name.orEmpty(),
|
||||
typeLayout = targetType?.layout,
|
||||
icon = icon
|
||||
typeLayout = obj.layout,
|
||||
icon = ObjectIcon.from(
|
||||
obj = obj,
|
||||
layout = obj.layout,
|
||||
builder = urlBuilder
|
||||
)
|
||||
)
|
||||
}
|
||||
}.collectLatest { views ->
|
||||
|
|
|
@ -105,7 +105,8 @@ open class DashboardTestSetup {
|
|||
searchRecentObjects = searchRecentObjects,
|
||||
searchInboxObjects = searchInboxObjects,
|
||||
searchObjectSets = searchObjectSets,
|
||||
getFlavourConfig = getFlavourConfig
|
||||
getFlavourConfig = getFlavourConfig,
|
||||
urlBuilder = builder
|
||||
)
|
||||
|
||||
fun stubGetConfig(response: Either.Right<Config>) {
|
||||
|
|
|
@ -114,7 +114,8 @@ class HomeDashboardViewModelTest {
|
|||
searchRecentObjects = searchRecentObjects,
|
||||
searchInboxObjects = searchInboxObjects,
|
||||
searchObjectSets = searchObjectSets,
|
||||
getFlavourConfig = getFlavourConfig
|
||||
getFlavourConfig = getFlavourConfig,
|
||||
urlBuilder = builder
|
||||
)
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue