mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2320 Gallery Installation | Tech | MVVM components (#1009)
This commit is contained in:
parent
c0ee5ef7eb
commit
fa08c1325b
14 changed files with 324 additions and 1 deletions
|
@ -171,6 +171,7 @@ dependencies {
|
|||
implementation project(':ui-settings')
|
||||
implementation project(':crash-reporting')
|
||||
implementation project(':payments')
|
||||
implementation project(':gallery-experience')
|
||||
|
||||
//Compile time dependencies
|
||||
kapt libs.daggerCompiler
|
||||
|
|
|
@ -60,6 +60,7 @@ import com.anytypeio.anytype.di.feature.ViewerFilterModule
|
|||
import com.anytypeio.anytype.di.feature.ViewerSortModule
|
||||
import com.anytypeio.anytype.di.feature.auth.DaggerDeletedAccountComponent
|
||||
import com.anytypeio.anytype.di.feature.cover.UnsplashModule
|
||||
import com.anytypeio.anytype.di.feature.gallery.DaggerGalleryInstallationComponent
|
||||
import com.anytypeio.anytype.di.feature.home.DaggerHomeScreenComponent
|
||||
import com.anytypeio.anytype.di.feature.library.DaggerLibraryComponent
|
||||
import com.anytypeio.anytype.di.feature.multiplayer.DaggerRequestJoinSpaceComponent
|
||||
|
@ -1075,6 +1076,10 @@ class ComponentManager(
|
|||
DaggerPaymentsComponent.factory().create(findComponentDependencies())
|
||||
}
|
||||
|
||||
val galleryInstallationsComponent = Component {
|
||||
DaggerGalleryInstallationComponent.factory().create(findComponentDependencies())
|
||||
}
|
||||
|
||||
class Component<T>(private val builder: () -> T) {
|
||||
|
||||
private var instance: T? = null
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package com.anytypeio.anytype.di.feature.gallery
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
|
||||
import com.anytypeio.anytype.di.common.ComponentDependencies
|
||||
import com.anytypeio.anytype.gallery_experience.viewmodel.GalleryInstallationViewModelFactory
|
||||
import com.anytypeio.anytype.ui.gallery.GalleryInstallationFragment
|
||||
import dagger.Binds
|
||||
import dagger.Component
|
||||
import dagger.Module
|
||||
|
||||
@Component(
|
||||
dependencies = [GalleryInstallationComponentDependencies::class],
|
||||
modules = [
|
||||
GalleryInstallationModule::class,
|
||||
GalleryInstallationModule.Declarations::class
|
||||
]
|
||||
)
|
||||
@PerScreen
|
||||
interface GalleryInstallationComponent {
|
||||
|
||||
@Component.Factory
|
||||
interface Factory {
|
||||
fun create(dependencies: GalleryInstallationComponentDependencies): GalleryInstallationComponent
|
||||
}
|
||||
|
||||
fun inject(fragment: GalleryInstallationFragment)
|
||||
}
|
||||
|
||||
@Module
|
||||
object GalleryInstallationModule {
|
||||
|
||||
@Module
|
||||
interface Declarations {
|
||||
|
||||
@PerScreen
|
||||
@Binds
|
||||
fun bindViewModelFactory(
|
||||
factory: GalleryInstallationViewModelFactory
|
||||
): ViewModelProvider.Factory
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
interface GalleryInstallationComponentDependencies : ComponentDependencies {
|
||||
fun analytics(): Analytics
|
||||
}
|
|
@ -19,6 +19,7 @@ import com.anytypeio.anytype.di.feature.ObjectTypeChangeSubComponent
|
|||
import com.anytypeio.anytype.di.feature.PersonalizationSettingsSubComponent
|
||||
import com.anytypeio.anytype.di.feature.SplashDependencies
|
||||
import com.anytypeio.anytype.di.feature.auth.DeletedAccountDependencies
|
||||
import com.anytypeio.anytype.di.feature.gallery.GalleryInstallationComponentDependencies
|
||||
import com.anytypeio.anytype.di.feature.home.HomeScreenDependencies
|
||||
import com.anytypeio.anytype.di.feature.library.LibraryDependencies
|
||||
import com.anytypeio.anytype.di.feature.multiplayer.RequestJoinSpaceDependencies
|
||||
|
@ -112,7 +113,8 @@ interface MainComponent :
|
|||
ShareSpaceDependencies,
|
||||
SpaceJoinRequestDependencies,
|
||||
RequestJoinSpaceDependencies,
|
||||
PaymentsComponentDependencies
|
||||
PaymentsComponentDependencies,
|
||||
GalleryInstallationComponentDependencies
|
||||
{
|
||||
|
||||
fun inject(app: AndroidApplication)
|
||||
|
@ -308,4 +310,9 @@ private abstract class ComponentDependenciesModule private constructor() {
|
|||
@IntoMap
|
||||
@ComponentDependenciesKey(RequestJoinSpaceDependencies::class)
|
||||
abstract fun provideRequestToJoinSpaceDependencies(component: MainComponent): ComponentDependencies
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ComponentDependenciesKey(GalleryInstallationComponentDependencies::class)
|
||||
abstract fun provideGalleryInstallationDependencies(component: MainComponent): ComponentDependencies
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package com.anytypeio.anytype.ui.gallery
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.anytypeio.anytype.core_ui.common.ComposeDialogView
|
||||
import com.anytypeio.anytype.core_utils.ext.subscribe
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.gallery_experience.models.GalleryInstallationNavigation
|
||||
import com.anytypeio.anytype.gallery_experience.screens.GalleryInstallationScreen
|
||||
import com.anytypeio.anytype.gallery_experience.screens.GalleryInstallationSpacesScreen
|
||||
import com.anytypeio.anytype.gallery_experience.viewmodel.GalleryInstallationViewModel
|
||||
import com.anytypeio.anytype.gallery_experience.viewmodel.GalleryInstallationViewModelFactory
|
||||
import com.google.accompanist.navigation.material.BottomSheetNavigator
|
||||
import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi
|
||||
import com.google.accompanist.navigation.material.ModalBottomSheetLayout
|
||||
import com.google.accompanist.navigation.material.bottomSheet
|
||||
import com.google.accompanist.navigation.material.rememberBottomSheetNavigator
|
||||
import javax.inject.Inject
|
||||
|
||||
class GalleryInstallationFragment : BaseBottomSheetComposeFragment() {
|
||||
|
||||
@Inject
|
||||
lateinit var factory: GalleryInstallationViewModelFactory
|
||||
private val vm by viewModels<GalleryInstallationViewModel> { factory }
|
||||
private lateinit var navController: NavHostController
|
||||
|
||||
@OptIn(ExperimentalMaterialNavigationApi::class)
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
return ComposeDialogView(context = requireContext(), dialog = requireDialog()).apply {
|
||||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
setContent {
|
||||
MaterialTheme {
|
||||
val bottomSheetNavigator = rememberBottomSheetNavigator()
|
||||
navController = rememberNavController(bottomSheetNavigator)
|
||||
SetupNavigation(bottomSheetNavigator, navController)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
jobs += subscribe(vm.command) { command ->
|
||||
when (command) {
|
||||
GalleryInstallationNavigation.Main -> navController.navigate(
|
||||
GalleryInstallationNavigation.Main.route
|
||||
)
|
||||
|
||||
GalleryInstallationNavigation.Dismiss -> navController.popBackStack()
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialNavigationApi::class)
|
||||
@Composable
|
||||
private fun SetupNavigation(
|
||||
bottomSheetNavigator: BottomSheetNavigator,
|
||||
navController: NavHostController
|
||||
) {
|
||||
ModalBottomSheetLayout(bottomSheetNavigator = bottomSheetNavigator) {
|
||||
NavigationGraph(navController = navController)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialNavigationApi::class)
|
||||
@Composable
|
||||
private fun NavigationGraph(navController: NavHostController) {
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = GalleryInstallationNavigation.Main.route
|
||||
) {
|
||||
composable(GalleryInstallationNavigation.Main.route) {
|
||||
InitMainScreen()
|
||||
}
|
||||
bottomSheet(GalleryInstallationNavigation.Spaces.route) {
|
||||
InitSpacesScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun InitMainScreen() {
|
||||
skipCollapsed()
|
||||
expand()
|
||||
GalleryInstallationScreen(
|
||||
state = vm.mainState.collectAsStateWithLifecycle().value
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun InitSpacesScreen() {
|
||||
GalleryInstallationSpacesScreen()
|
||||
}
|
||||
|
||||
override fun injectDependencies() {
|
||||
componentManager().galleryInstallationsComponent.get().inject(this)
|
||||
}
|
||||
|
||||
override fun releaseDependencies() {
|
||||
componentManager().galleryInstallationsComponent.release()
|
||||
}
|
||||
}
|
57
gallery-experience/build.gradle
Normal file
57
gallery-experience/build.gradle
Normal file
|
@ -0,0 +1,57 @@
|
|||
plugins {
|
||||
id "com.android.library"
|
||||
id "kotlin-android"
|
||||
}
|
||||
|
||||
android {
|
||||
|
||||
def config = rootProject.extensions.getByName("ext")
|
||||
|
||||
buildFeatures {
|
||||
compose true
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion libs.versions.composeKotlinCompilerVersion.get()
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
}
|
||||
kotlin {
|
||||
jvmToolchain(17)
|
||||
}
|
||||
namespace 'com.anytypeio.anytype.galleryexperience'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(':domain')
|
||||
implementation project(':core-ui')
|
||||
implementation project(':analytics')
|
||||
implementation project(':core-models')
|
||||
implementation project(':core-utils')
|
||||
implementation project(':localization')
|
||||
implementation project(':presentation')
|
||||
implementation project(':library-emojifier')
|
||||
|
||||
compileOnly libs.javaxInject
|
||||
|
||||
implementation libs.lifecycleViewModel
|
||||
implementation libs.lifecycleRuntime
|
||||
|
||||
implementation libs.appcompat
|
||||
implementation libs.compose
|
||||
implementation libs.composeFoundation
|
||||
implementation libs.composeToolingPreview
|
||||
implementation libs.composeMaterial3
|
||||
|
||||
implementation libs.coilCompose
|
||||
|
||||
debugImplementation libs.composeTooling
|
||||
|
||||
implementation libs.timber
|
||||
|
||||
testImplementation libs.junit
|
||||
testImplementation libs.kotlinTest
|
||||
}
|
1
gallery-experience/src/main/AndroidManifest.xml
Normal file
1
gallery-experience/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1 @@
|
|||
<manifest />
|
|
@ -0,0 +1,15 @@
|
|||
package com.anytypeio.anytype.gallery_experience.models
|
||||
|
||||
sealed class GalleryInstallationState {
|
||||
object Hidden : GalleryInstallationState()
|
||||
object Loading : GalleryInstallationState()
|
||||
object Success : GalleryInstallationState()
|
||||
}
|
||||
|
||||
sealed class GalleryInstallationNavigation(val route: String) {
|
||||
object Main : GalleryInstallationNavigation("main")
|
||||
object Spaces : GalleryInstallationNavigation("spaces")
|
||||
object Success : GalleryInstallationNavigation("success")
|
||||
object Error : GalleryInstallationNavigation("error")
|
||||
object Dismiss : GalleryInstallationNavigation("")
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.anytypeio.anytype.gallery_experience.screens
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.anytypeio.anytype.gallery_experience.models.GalleryInstallationState
|
||||
|
||||
@Composable
|
||||
fun GalleryInstallationScreen(state: GalleryInstallationState) {
|
||||
}
|
||||
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun GalleryInstallationScreenPreview() {
|
||||
GalleryInstallationScreen(GalleryInstallationState.Success)
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.anytypeio.anytype.gallery_experience.screens
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
||||
@Composable
|
||||
fun GalleryInstallationSpacesScreen() {
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun GallerySpacesScreenPreview() {
|
||||
GalleryInstallationSpacesScreen()
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.anytypeio.anytype.gallery_experience.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.gallery_experience.models.GalleryInstallationNavigation
|
||||
import com.anytypeio.anytype.gallery_experience.models.GalleryInstallationState
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import timber.log.Timber
|
||||
|
||||
class GalleryInstallationViewModel(
|
||||
private val analytics: Analytics,
|
||||
) : ViewModel() {
|
||||
|
||||
val mainState = MutableStateFlow<GalleryInstallationState>(GalleryInstallationState.Hidden)
|
||||
val command = MutableStateFlow<GalleryInstallationNavigation?>(null)
|
||||
|
||||
init {
|
||||
Timber.d("GalleryInstallationViewModel init")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.anytypeio.anytype.gallery_experience.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import javax.inject.Inject
|
||||
|
||||
class GalleryInstallationViewModelFactory@Inject constructor(
|
||||
private val analytics: Analytics,
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return GalleryInstallationViewModel(
|
||||
analytics = analytics,
|
||||
) as T
|
||||
}
|
||||
}
|
2
gallery-experience/src/main/res/values/strings.xml
Normal file
2
gallery-experience/src/main/res/values/strings.xml
Normal file
|
@ -0,0 +1,2 @@
|
|||
<resources>
|
||||
</resources>
|
|
@ -59,3 +59,4 @@ include ':ui-settings'
|
|||
include ':crash-reporting'
|
||||
include ':localization'
|
||||
include ':payments'
|
||||
include ':gallery-experience'
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue