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:
parent
878f84a052
commit
ee4c810bf6
12 changed files with 372 additions and 0 deletions
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
14
core-ui/src/main/res/drawable/ic_widget_type_link.xml
Normal file
14
core-ui/src/main/res/drawable/ic_widget_type_link.xml
Normal 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>
|
38
core-ui/src/main/res/drawable/ic_widget_type_list.xml
Normal file
38
core-ui/src/main/res/drawable/ic_widget_type_list.xml
Normal 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>
|
51
core-ui/src/main/res/drawable/ic_widget_type_tree.xml
Normal file
51
core-ui/src/main/res/drawable/ic_widget_type_tree.xml
Normal 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>
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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()
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue