Benoit Marty
12 months ago
committed by
GitHub
17 changed files with 315 additions and 5 deletions
Binary file not shown.
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
plugins { |
||||
id("io.element.android-library") |
||||
} |
||||
|
||||
android { |
||||
namespace = "io.element.android.features.${MODULE_NAME}.api" |
||||
} |
||||
|
||||
dependencies { |
||||
implementation(projects.libraries.architecture) |
||||
} |
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
plugins { |
||||
id("io.element.android-compose-library") |
||||
alias(libs.plugins.anvil) |
||||
alias(libs.plugins.ksp) |
||||
id("kotlin-parcelize") |
||||
} |
||||
|
||||
android { |
||||
namespace = "io.element.android.features.${MODULE_NAME}.impl" |
||||
} |
||||
|
||||
anvil { |
||||
generateDaggerFactories.set(true) |
||||
} |
||||
|
||||
dependencies { |
||||
implementation(projects.anvilannotations) |
||||
anvil(projects.anvilcodegen) |
||||
api(projects.features.${MODULE_NAME}.api) |
||||
implementation(projects.libraries.core) |
||||
implementation(projects.libraries.architecture) |
||||
implementation(projects.libraries.matrix.api) |
||||
implementation(projects.libraries.matrixui) |
||||
implementation(projects.libraries.designsystem) |
||||
|
||||
testImplementation(libs.test.junit) |
||||
testImplementation(libs.coroutines.test) |
||||
testImplementation(libs.molecule.runtime) |
||||
testImplementation(libs.test.truth) |
||||
testImplementation(libs.test.turbine) |
||||
testImplementation(projects.libraries.matrix.test) |
||||
|
||||
ksp(libs.showkase.processor) |
||||
} |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
package io.element.android.features.${MODULE_NAME}.api |
||||
|
||||
import com.bumble.appyx.core.modality.BuildContext |
||||
import com.bumble.appyx.core.node.Node |
||||
import com.bumble.appyx.core.plugin.Plugin |
||||
import io.element.android.libraries.architecture.FeatureEntryPoint |
||||
|
||||
interface ${FEATURE_NAME}EntryPoint : FeatureEntryPoint { |
||||
|
||||
fun nodeBuilder(parentNode: Node, buildContext: BuildContext): NodeBuilder |
||||
|
||||
interface NodeBuilder { |
||||
fun callback(callback: Callback): NodeBuilder |
||||
fun build(): Node |
||||
} |
||||
|
||||
interface Callback : Plugin { |
||||
// Add your callbacks |
||||
} |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
package io.element.android.features.${MODULE_NAME}.impl |
||||
|
||||
import com.bumble.appyx.core.modality.BuildContext |
||||
import com.bumble.appyx.core.node.Node |
||||
import com.bumble.appyx.core.plugin.Plugin |
||||
import com.squareup.anvil.annotations.ContributesBinding |
||||
import io.element.android.features.${MODULE_NAME}.api.${FEATURE_NAME}EntryPoint |
||||
import io.element.android.libraries.architecture.createNode |
||||
import io.element.android.libraries.di.AppScope |
||||
import javax.inject.Inject |
||||
|
||||
@ContributesBinding(AppScope::class) |
||||
class Default${FEATURE_NAME}EntryPoint @Inject constructor() : ${FEATURE_NAME}EntryPoint { |
||||
|
||||
override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): ${FEATURE_NAME}EntryPoint.NodeBuilder { |
||||
val plugins = ArrayList<Plugin>() |
||||
|
||||
return object : ${FEATURE_NAME}EntryPoint.NodeBuilder { |
||||
|
||||
override fun callback(callback: ${FEATURE_NAME}EntryPoint.Callback): ${FEATURE_NAME}EntryPoint.NodeBuilder { |
||||
plugins += callback |
||||
return this |
||||
} |
||||
|
||||
override fun build(): Node { |
||||
return parentNode.createNode<${FEATURE_NAME}FlowNode>(buildContext, plugins) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
package io.element.android.features.${MODULE_NAME}.impl |
||||
|
||||
import android.os.Parcelable |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.ui.Modifier |
||||
import com.bumble.appyx.core.composable.Children |
||||
import com.bumble.appyx.core.modality.BuildContext |
||||
import com.bumble.appyx.core.node.Node |
||||
import com.bumble.appyx.core.plugin.Plugin |
||||
import com.bumble.appyx.navmodel.backstack.BackStack |
||||
import com.bumble.appyx.navmodel.backstack.operation.push |
||||
import dagger.assisted.Assisted |
||||
import dagger.assisted.AssistedInject |
||||
import io.element.android.anvilannotations.ContributesNode |
||||
import io.element.android.libraries.architecture.BackstackNode |
||||
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler |
||||
import io.element.android.libraries.architecture.createNode |
||||
import io.element.android.libraries.di.AppScope |
||||
import kotlinx.parcelize.Parcelize |
||||
|
||||
// CHANGE THE SCOPE |
||||
@ContributesNode(AppScope::class) |
||||
class ${FEATURE_NAME}FlowNode @AssistedInject constructor( |
||||
@Assisted buildContext: BuildContext, |
||||
@Assisted plugins: List<Plugin>, |
||||
) : BackstackNode<${FEATURE_NAME}FlowNode.NavTarget>( |
||||
backstack = BackStack( |
||||
initialElement = NavTarget.Root, |
||||
savedStateMap = buildContext.savedStateMap, |
||||
), |
||||
buildContext = buildContext, |
||||
plugins = plugins, |
||||
) { |
||||
|
||||
sealed interface NavTarget : Parcelable { |
||||
@Parcelize |
||||
object Root : NavTarget |
||||
} |
||||
|
||||
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { |
||||
return when (navTarget) { |
||||
NavTarget.Root -> { |
||||
//Give your root node or completely delete this FlowNode if you have only one node. |
||||
createNode<>(buildContext) |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Composable |
||||
override fun View(modifier: Modifier) { |
||||
Children( |
||||
navModel = backstack, |
||||
modifier = modifier, |
||||
transitionHandler = rememberDefaultTransitionHandler(), |
||||
) |
||||
} |
||||
} |
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end |
||||
|
||||
import androidx.compose.runtime.Composable |
||||
import io.element.android.libraries.architecture.Presenter |
||||
import javax.inject.Inject |
||||
|
||||
class ${NAME}Presenter @Inject constructor() : Presenter<${NAME}State> { |
||||
|
||||
@Composable |
||||
override fun present(): ${NAME}State { |
||||
|
||||
fun handleEvents(event: ${NAME}Events) { |
||||
when (event) { |
||||
${NAME}Events.MyEvent -> Unit |
||||
} |
||||
} |
||||
|
||||
return ${NAME}State( |
||||
eventSink = ::handleEvents |
||||
) |
||||
} |
||||
} |
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end |
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider |
||||
|
||||
open class ${NAME}StateProvider : PreviewParameterProvider<${NAME}State> { |
||||
override val values: Sequence<${NAME}State> |
||||
get() = sequenceOf( |
||||
a${NAME}State(), |
||||
// Add other states here |
||||
) |
||||
} |
||||
|
||||
fun a${NAME}State() = ${NAME}State( |
||||
eventSink = {} |
||||
) |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end |
||||
|
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.ui.Modifier |
||||
import com.bumble.appyx.core.modality.BuildContext |
||||
import com.bumble.appyx.core.node.Node |
||||
import com.bumble.appyx.core.plugin.Plugin |
||||
import dagger.assisted.Assisted |
||||
import dagger.assisted.AssistedInject |
||||
import io.element.android.anvilannotations.ContributesNode |
||||
import io.element.android.libraries.di.AppScope |
||||
|
||||
// CHANGE THE SCOPE |
||||
@ContributesNode(AppScope::class) |
||||
class ${NAME}Node @AssistedInject constructor( |
||||
@Assisted buildContext: BuildContext, |
||||
@Assisted plugins: List<Plugin>, |
||||
private val presenter: ${NAME}Presenter, |
||||
) : Node(buildContext, plugins = plugins) { |
||||
|
||||
@Composable |
||||
override fun View(modifier: Modifier) { |
||||
val state = presenter.present() |
||||
${NAME}View( |
||||
state = state, |
||||
modifier = modifier |
||||
) |
||||
} |
||||
} |
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end |
||||
|
||||
import androidx.compose.foundation.layout.Box |
||||
import androidx.compose.material3.MaterialTheme |
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.ui.Alignment |
||||
import androidx.compose.ui.Modifier |
||||
import androidx.compose.ui.tooling.preview.Preview |
||||
import androidx.compose.ui.tooling.preview.PreviewParameter |
||||
import io.element.android.libraries.designsystem.preview.ElementPreview |
||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight |
||||
import io.element.android.libraries.designsystem.theme.components.Text |
||||
|
||||
@Composable |
||||
fun ${NAME}View( |
||||
state: ${NAME}State, |
||||
modifier: Modifier = Modifier, |
||||
) { |
||||
Box(modifier, contentAlignment = Alignment.Center) { |
||||
Text( |
||||
"${NAME} feature view", |
||||
color = MaterialTheme.colorScheme.primary, |
||||
) |
||||
} |
||||
} |
||||
|
||||
@PreviewsDayNight |
||||
@Composable |
||||
internal fun ${NAME}ViewPreview( |
||||
@PreviewParameter(${NAME}StateProvider::class) state: ${NAME}State |
||||
) = ElementPreview { |
||||
${NAME}View( |
||||
state = state, |
||||
) |
||||
} |
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end |
||||
|
||||
// TODO add your ui models. Remove the eventSink if you don't have events. |
||||
// Do not use default value, so no member get forgotten in the presenters. |
||||
data class ${NAME}State( |
||||
val eventSink: (${NAME}Events) -> Unit |
||||
) |
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}#end |
||||
|
||||
// TODO Add your events or remove the file completely if no events |
||||
sealed interface ${NAME}Events { |
||||
data object MyEvent: ${NAME}Events |
||||
} |
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
<application> |
||||
<component name="ExportableFileTemplateSettings"> |
||||
<default_templates> |
||||
<template name="Template Presentation Classes.kt" file-name="${NAME}Presenter" reformat="true" live-template-enabled="false"> |
||||
<template name="Template Presentation Classes.kt.child.0.kt" file-name="${NAME}StateProvider" reformat="true" live-template-enabled="false" /> |
||||
<template name="Template Presentation Classes.kt.child.1.kt" file-name="${NAME}Node" reformat="true" live-template-enabled="false" /> |
||||
<template name="Template Presentation Classes.kt.child.2.kt" file-name="${NAME}View" reformat="true" live-template-enabled="false" /> |
||||
<template name="Template Presentation Classes.kt.child.3.kt" file-name="${NAME}State" reformat="true" live-template-enabled="false" /> |
||||
<template name="Template Presentation Classes.kt.child.4.kt" file-name="${NAME}Events" reformat="true" live-template-enabled="false" /> |
||||
</template> |
||||
<template name="Template Presentation Classes.kt.child.0.kt" file-name="${NAME}StateProvider" reformat="true" live-template-enabled="false" /> |
||||
<template name="Template Presentation Classes.kt.child.1.kt" file-name="${NAME}Node" reformat="true" live-template-enabled="false" /> |
||||
<template name="Template Presentation Classes.kt.child.2.kt" file-name="${NAME}View" reformat="true" live-template-enabled="false" /> |
||||
<template name="Template Presentation Classes.kt.child.3.kt" file-name="${NAME}State" reformat="true" live-template-enabled="false" /> |
||||
<template name="Template Presentation Classes.kt.child.4.kt" file-name="${NAME}Events" reformat="true" live-template-enabled="false" /> |
||||
</default_templates> |
||||
</component> |
||||
</application> |
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash |
||||
|
||||
# |
||||
# Copyright 2023 New Vector Ltd |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
# |
||||
|
||||
echo "Zipping the contents of the 'files' directory..." |
||||
|
||||
# Ensure tmp folder exists |
||||
mkdir -p tmp |
||||
|
||||
rm -f ./tmp/file_templates.zip |
||||
pushd ./tools/templates/files |
||||
zip -r ../../../tmp/file_templates.zip . |
||||
popd |
Loading…
Reference in new issue