1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-10 10:00:44 +09:00

DROID-935 Widgets | Enhancement | Layout + MVVM setup for widget type picker (#2904)

This commit is contained in:
Evgenii Kozlov 2023-02-08 12:06:21 +01:00 committed by GitHub
parent 878f84a052
commit ee4c810bf6
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 372 additions and 0 deletions

View file

@ -81,6 +81,7 @@ import com.anytypeio.anytype.di.feature.settings.LogoutWarningModule
import com.anytypeio.anytype.di.feature.settings.MainSettingsModule
import com.anytypeio.anytype.di.feature.wallpaper.WallpaperSelectModule
import com.anytypeio.anytype.di.feature.widgets.SelectWidgetSourceModule
import com.anytypeio.anytype.di.feature.widgets.SelectWidgetTypeModule
import com.anytypeio.anytype.di.main.MainComponent
class ComponentManager(
@ -190,6 +191,14 @@ class ComponentManager(
.build()
}
val selectWidgetTypeSubcomponent = Component {
homeScreenComponent
.get()
.selectWidgetTypeBuilder()
.module(SelectWidgetTypeModule)
.build()
}
val wallpaperSelectComponent = Component {
main
.wallpaperSelectComponent()

View file

@ -6,6 +6,7 @@ import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.di.common.ComponentDependencies
import com.anytypeio.anytype.di.feature.widgets.SelectWidgetSourceSubcomponent
import com.anytypeio.anytype.di.feature.widgets.SelectWidgetTypeSubcomponent
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.repo.BlockRepository
@ -47,6 +48,7 @@ interface HomeScreenComponent {
fun inject(fragment: HomeScreenFragment)
fun selectWidgetSourceBuilder(): SelectWidgetSourceSubcomponent.Builder
fun selectWidgetTypeBuilder(): SelectWidgetTypeSubcomponent.Builder
}
@Module

View file

@ -0,0 +1,35 @@
package com.anytypeio.anytype.di.feature.widgets
import com.anytypeio.anytype.core_utils.di.scope.PerModal
import com.anytypeio.anytype.presentation.widgets.SelectWidgetTypeViewModel
import com.anytypeio.anytype.ui.widgets.SelectWidgetTypeFragment
import dagger.Module
import dagger.Provides
import dagger.Subcomponent
@Subcomponent(
modules = [SelectWidgetTypeModule::class]
)
@PerModal
interface SelectWidgetTypeSubcomponent {
@Subcomponent.Builder
interface Builder {
fun module(module: SelectWidgetTypeModule): Builder
fun build(): SelectWidgetTypeSubcomponent
}
fun inject(fragment: SelectWidgetTypeFragment)
}
@Module
object SelectWidgetTypeModule {
@JvmStatic
@PerModal
@Provides
fun factory(
): SelectWidgetTypeViewModel.Factory = SelectWidgetTypeViewModel.Factory(
// TODO
)
}

View file

@ -0,0 +1,43 @@
package com.anytypeio.anytype.ui.widgets
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.fragment.app.viewModels
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
import com.anytypeio.anytype.di.common.componentManager
import com.anytypeio.anytype.presentation.widgets.SelectWidgetTypeViewModel
import javax.inject.Inject
class SelectWidgetTypeFragment : BaseBottomSheetComposeFragment() {
private val vm by viewModels<SelectWidgetTypeViewModel> { factory }
@Inject
lateinit var factory: SelectWidgetTypeViewModel.Factory
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = ComposeView(requireContext()).apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
SelectWidgetTypeScreen(
views = emptyList(),
onViewClicked = {}
)
}
}
override fun injectDependencies() {
componentManager().selectWidgetTypeSubcomponent.get().inject(this)
}
override fun releaseDependencies() {
componentManager().selectWidgetTypeSubcomponent.release()
}
}

View file

@ -0,0 +1,131 @@
package com.anytypeio.anytype.ui.widgets
import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_ui.foundation.Divider
import com.anytypeio.anytype.core_ui.foundation.Dragger
import com.anytypeio.anytype.core_ui.foundation.Toolbar
import com.anytypeio.anytype.presentation.widgets.WidgetTypeView
@Composable
fun SelectWidgetTypeScreen(
views: List<WidgetTypeView>,
onViewClicked: (WidgetTypeView) -> Unit
) {
Column {
Box(
Modifier
.padding(vertical = 6.dp)
.align(Alignment.CenterHorizontally)
) {
Dragger()
}
Toolbar(stringResource(R.string.widget_type))
views.forEachIndexed { index, type ->
when (type) {
is WidgetTypeView.Link -> WidgetTypeItem(
title = stringResource(
R.string.widget_type_link
),
subtitle = stringResource(
R.string.widget_type_link_description
),
icon = R.drawable.ic_widget_type_link,
isChecked = type.isSelected,
onClick = { onViewClicked(type) }
)
is WidgetTypeView.List -> WidgetTypeItem(
title = stringResource(
R.string.widget_type_list
),
subtitle = stringResource(
R.string.widget_type_list_description
),
icon = R.drawable.ic_widget_type_list,
isChecked = type.isSelected,
onClick = { onViewClicked(type) }
)
is WidgetTypeView.Tree -> WidgetTypeItem(
title = stringResource(
R.string.widget_type_tree
),
subtitle = stringResource(
R.string.widget_type_tree_description
),
icon = R.drawable.ic_widget_type_tree,
isChecked = type.isSelected,
onClick = { onViewClicked(type) }
)
}
if (index != views.lastIndex) {
Divider(paddingStart = 76.dp)
}
}
Spacer(modifier = Modifier.height(52.dp))
}
}
@Composable
fun WidgetTypeItem(
title: String,
subtitle: String,
@DrawableRes icon: Int,
isChecked: Boolean = false,
onClick: () -> Unit
) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(60.dp)
.clickable { onClick() }
) {
Image(
painterResource(icon),
contentDescription = "Widget type icon",
modifier = Modifier
.align(Alignment.CenterStart)
.padding(start = 20.dp)
)
Text(
modifier = Modifier
.align(Alignment.TopStart)
.padding(start = 70.dp, top = 11.dp),
text = title,
color = colorResource(id = R.color.text_primary)
)
Text(
modifier = Modifier
.align(Alignment.BottomStart)
.padding(start = 70.dp, bottom = 11.dp),
text = subtitle,
color = colorResource(id = R.color.text_secondary)
)
if (isChecked) {
Image(
painterResource(R.drawable.ic_widget_type_checked_checkbox),
contentDescription = "Widget type checkbox icon",
modifier = Modifier
.align(Alignment.CenterEnd)
.padding(end = 20.dp)
)
}
}
}

View file

@ -316,5 +316,12 @@ Do the computation of an expensive paragraph of text on a background thread:
<string name="create_widget">Create a widget</string>
<string name="edit_widgets">Edit widgets</string>
<string name="widget_source">Widget source</string>
<string name="widget_type">Widget type</string>
<string name="widget_type_tree">Tree</string>
<string name="widget_type_tree_description">Hierarchical structure of object</string>
<string name="widget_type_link">Link</string>
<string name="widget_type_link_description">Compact version of the object</string>
<string name="widget_type_list_description">Widget with list view of set object</string>
<string name="widget_type_list">List</string>
</resources>

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<group>
<clip-path
android:pathData="M0,0h24v24h-24z"/>
<path
android:pathData="M18.633,6.402L11.131,18.191L5.47,12.53L6.53,11.469L10.869,15.808L17.367,5.597L18.633,6.402Z"
android:fillColor="@color/glyph_selected"
android:fillType="evenOdd"/>
</group>
</vector>

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:strokeWidth="1"
android:pathData="M4,12.5L36,12.5A3.5,3.5 0,0 1,39.5 16L39.5,24A3.5,3.5 0,0 1,36 27.5L4,27.5A3.5,3.5 0,0 1,0.5 24L0.5,16A3.5,3.5 0,0 1,4 12.5z"
android:fillColor="#00000000"
android:strokeColor="@color/shape_primary"/>
<path
android:pathData="M6.75,19.25L33.25,19.25A0.75,0.75 0,0 1,34 20L34,20A0.75,0.75 0,0 1,33.25 20.75L6.75,20.75A0.75,0.75 0,0 1,6 20L6,20A0.75,0.75 0,0 1,6.75 19.25z"
android:fillColor="@color/glyph_active"/>
</vector>

View file

@ -0,0 +1,38 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<path
android:strokeWidth="1"
android:pathData="M6,0.5L34,0.5A5.5,5.5 0,0 1,39.5 6L39.5,34A5.5,5.5 0,0 1,34 39.5L6,39.5A5.5,5.5 0,0 1,0.5 34L0.5,6A5.5,5.5 0,0 1,6 0.5z"
android:fillColor="#00000000"
android:strokeColor="@color/shape_primary"/>
<path
android:pathData="M17.75,7.25L33.25,7.25A0.75,0.75 0,0 1,34 8L34,8A0.75,0.75 0,0 1,33.25 8.75L17.75,8.75A0.75,0.75 0,0 1,17 8L17,8A0.75,0.75 0,0 1,17.75 7.25z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M17.75,11.25L28.25,11.25A0.75,0.75 0,0 1,29 12L29,12A0.75,0.75 0,0 1,28.25 12.75L17.75,12.75A0.75,0.75 0,0 1,17 12L17,12A0.75,0.75 0,0 1,17.75 11.25z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M8,6L12,6A2,2 0,0 1,14 8L14,12A2,2 0,0 1,12 14L8,14A2,2 0,0 1,6 12L6,8A2,2 0,0 1,8 6z"
android:fillColor="@color/shape_primary"/>
<path
android:pathData="M17.75,17.25L33.25,17.25A0.75,0.75 0,0 1,34 18L34,18A0.75,0.75 0,0 1,33.25 18.75L17.75,18.75A0.75,0.75 0,0 1,17 18L17,18A0.75,0.75 0,0 1,17.75 17.25z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M17.75,21.25L28.25,21.25A0.75,0.75 0,0 1,29 22L29,22A0.75,0.75 0,0 1,28.25 22.75L17.75,22.75A0.75,0.75 0,0 1,17 22L17,22A0.75,0.75 0,0 1,17.75 21.25z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M8,16L12,16A2,2 0,0 1,14 18L14,22A2,2 0,0 1,12 24L8,24A2,2 0,0 1,6 22L6,18A2,2 0,0 1,8 16z"
android:fillColor="@color/shape_primary"/>
<path
android:pathData="M17.75,27.25L33.25,27.25A0.75,0.75 0,0 1,34 28L34,28A0.75,0.75 0,0 1,33.25 28.75L17.75,28.75A0.75,0.75 0,0 1,17 28L17,28A0.75,0.75 0,0 1,17.75 27.25z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M17.75,31.25L28.25,31.25A0.75,0.75 0,0 1,29 32L29,32A0.75,0.75 0,0 1,28.25 32.75L17.75,32.75A0.75,0.75 0,0 1,17 32L17,32A0.75,0.75 0,0 1,17.75 31.25z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M8,26L12,26A2,2 0,0 1,14 28L14,32A2,2 0,0 1,12 34L8,34A2,2 0,0 1,6 32L6,28A2,2 0,0 1,8 26z"
android:fillColor="@color/shape_primary"/>
</vector>

View file

@ -0,0 +1,51 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="40dp"
android:height="40dp"
android:viewportWidth="40"
android:viewportHeight="40">
<group>
<clip-path
android:pathData="M0,0h40v40h-40z"/>
<path
android:strokeWidth="1"
android:pathData="M6,0.5L34,0.5A5.5,5.5 0,0 1,39.5 6L39.5,34A5.5,5.5 0,0 1,34 39.5L6,39.5A5.5,5.5 0,0 1,0.5 34L0.5,6A5.5,5.5 0,0 1,6 0.5z"
android:fillColor="#00000000"
android:strokeColor="@color/shape_primary"/>
<path
android:pathData="M10.75,6.25L33.25,6.25A0.75,0.75 0,0 1,34 7L34,7A0.75,0.75 0,0 1,33.25 7.75L10.75,7.75A0.75,0.75 0,0 1,10 7L10,7A0.75,0.75 0,0 1,10.75 6.25z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M6,7C6,6.448 6.448,6 7,6C7.552,6 8,6.448 8,7C8,7.552 7.552,8 7,8C6.448,8 6,7.552 6,7Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M6,12C6,11.448 6.448,11 7,11C7.552,11 8,11.448 8,12C8,12.552 7.552,13 7,13C6.448,13 6,12.552 6,12Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M10,17C10,16.448 10.448,16 11,16C11.552,16 12,16.448 12,17C12,17.552 11.552,18 11,18C10.448,18 10,17.552 10,17Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M14,22C14,21.448 14.448,21 15,21C15.552,21 16,21.448 16,22C16,22.552 15.552,23 15,23C14.448,23 14,22.552 14,22Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M10,12C10,11.586 10.336,11.25 10.75,11.25H33.25C33.664,11.25 34,11.586 34,12C34,12.414 33.664,12.75 33.25,12.75H10.75C10.336,12.75 10,12.414 10,12Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M14.75,16.25L33.25,16.25A0.75,0.75 0,0 1,34 17L34,17A0.75,0.75 0,0 1,33.25 17.75L14.75,17.75A0.75,0.75 0,0 1,14 17L14,17A0.75,0.75 0,0 1,14.75 16.25z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M18.75,21.25L33.25,21.25A0.75,0.75 0,0 1,34 22L34,22A0.75,0.75 0,0 1,33.25 22.75L18.75,22.75A0.75,0.75 0,0 1,18 22L18,22A0.75,0.75 0,0 1,18.75 21.25z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M14,27C14,26.448 14.448,26 15,26C15.552,26 16,26.448 16,27C16,27.552 15.552,28 15,28C14.448,28 14,27.552 14,27Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M18.75,26.25L33.25,26.25A0.75,0.75 0,0 1,34 27L34,27A0.75,0.75 0,0 1,33.25 27.75L18.75,27.75A0.75,0.75 0,0 1,18 27L18,27A0.75,0.75 0,0 1,18.75 26.25z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M6,32C6,31.448 6.448,31 7,31C7.552,31 8,31.448 8,32C8,32.552 7.552,33 7,33C6.448,33 6,32.552 6,32Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M10.75,31.25L33.25,31.25A0.75,0.75 0,0 1,34 32L34,32A0.75,0.75 0,0 1,33.25 32.75L10.75,32.75A0.75,0.75 0,0 1,10 32L10,32A0.75,0.75 0,0 1,10.75 31.25z"
android:fillColor="@color/glyph_active"/>
</group>
</vector>

View file

@ -0,0 +1,20 @@
package com.anytypeio.anytype.presentation.widgets
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.anytypeio.anytype.presentation.common.BaseViewModel
class SelectWidgetTypeViewModel : BaseViewModel() {
class Factory(
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return SelectWidgetTypeViewModel(
) as T
}
}
}

View file

@ -0,0 +1,8 @@
package com.anytypeio.anytype.presentation.widgets
sealed class WidgetTypeView {
abstract val isSelected: Boolean
data class List(override val isSelected: Boolean) : WidgetTypeView()
data class Tree(override val isSelected: Boolean): WidgetTypeView()
data class Link(override val isSelected: Boolean): WidgetTypeView()
}