Merge branch 'develop' into feature/fga/improve_node_architecture
This commit is contained in:
commit
7455c4923f
57 changed files with 1061 additions and 54 deletions
|
|
@ -43,6 +43,7 @@ dependencies {
|
|||
implementation(projects.features.preferences.api)
|
||||
implementation(projects.features.logout.api)
|
||||
implementation(projects.features.onboarding.api)
|
||||
implementation(projects.features.createroom)
|
||||
|
||||
implementation(projects.libraries.core)
|
||||
implementation(projects.libraries.architecture)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ 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.features.createroom.CreateRoomFlowNode
|
||||
import io.element.android.features.preferences.api.PreferencesEntryPoint
|
||||
import io.element.android.features.roomlist.api.RoomListEntryPoint
|
||||
import io.element.android.libraries.architecture.BackstackNode
|
||||
|
|
@ -107,6 +108,9 @@ class LoggedInFlowNode @AssistedInject constructor(
|
|||
|
||||
@Parcelize
|
||||
object Settings : NavTarget
|
||||
|
||||
@Parcelize
|
||||
object CreateRoom : NavTarget
|
||||
}
|
||||
|
||||
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
||||
|
|
@ -120,6 +124,10 @@ class LoggedInFlowNode @AssistedInject constructor(
|
|||
override fun onSettingsClicked() {
|
||||
backstack.push(NavTarget.Settings)
|
||||
}
|
||||
|
||||
override fun onCreateRoomClicked() {
|
||||
backstack.push(NavTarget.CreateRoom)
|
||||
}
|
||||
}
|
||||
roomListEntryPoint
|
||||
.nodeBuilder(this, buildContext)
|
||||
|
|
@ -151,6 +159,9 @@ class LoggedInFlowNode @AssistedInject constructor(
|
|||
.callback(callback)
|
||||
.build()
|
||||
}
|
||||
NavTarget.CreateRoom -> {
|
||||
CreateRoomFlowNode(buildContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
1
changelog.d/94.wip
Normal file
1
changelog.d/94.wip
Normal file
|
|
@ -0,0 +1 @@
|
|||
[Create and join rooms] Start new chat screen (UI)
|
||||
1
features/createroom/.gitignore
vendored
Normal file
1
features/createroom/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
56
features/createroom/build.gradle.kts
Normal file
56
features/createroom/build.gradle.kts
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
// TODO: Remove once https://youtrack.jetbrains.com/issue/KTIJ-19369 is fixed
|
||||
@Suppress("DSL_SCOPE_VIOLATION")
|
||||
plugins {
|
||||
id("io.element.android-compose-library")
|
||||
alias(libs.plugins.ksp)
|
||||
alias(libs.plugins.anvil)
|
||||
id("kotlin-parcelize")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.features.createroom"
|
||||
}
|
||||
|
||||
anvil {
|
||||
generateDaggerFactories.set(true)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
anvil(projects.anvilcodegen)
|
||||
implementation(projects.anvilannotations)
|
||||
|
||||
implementation(projects.libraries.core)
|
||||
implementation(projects.libraries.architecture)
|
||||
implementation(projects.libraries.matrix.api)
|
||||
implementation(projects.libraries.matrixui)
|
||||
implementation(projects.libraries.designsystem)
|
||||
implementation(projects.libraries.elementresources)
|
||||
implementation(projects.libraries.uiStrings)
|
||||
|
||||
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)
|
||||
|
||||
androidTestImplementation(libs.test.junitext)
|
||||
|
||||
ksp(libs.showkase.processor)
|
||||
}
|
||||
0
features/createroom/consumer-rules.pro
Normal file
0
features/createroom/consumer-rules.pro
Normal file
21
features/createroom/proguard-rules.pro
vendored
Normal file
21
features/createroom/proguard-rules.pro
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
20
features/createroom/src/main/AndroidManifest.xml
Normal file
20
features/createroom/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 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.
|
||||
-->
|
||||
|
||||
<manifest>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package io.element.android.features.createroom
|
||||
|
||||
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.node.ParentNode
|
||||
import com.bumble.appyx.navmodel.backstack.BackStack
|
||||
import io.element.android.features.createroom.root.CreateRoomRootNode
|
||||
import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler
|
||||
import io.element.android.libraries.architecture.createNode
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
class CreateRoomFlowNode(
|
||||
buildContext: BuildContext,
|
||||
private val backstack: BackStack<NavTarget> = BackStack(
|
||||
initialElement = NavTarget.Root,
|
||||
savedStateMap = buildContext.savedStateMap,
|
||||
),
|
||||
) : ParentNode<CreateRoomFlowNode.NavTarget>(
|
||||
navModel = backstack,
|
||||
buildContext = buildContext
|
||||
) {
|
||||
|
||||
sealed interface NavTarget : Parcelable {
|
||||
@Parcelize
|
||||
object Root : NavTarget
|
||||
}
|
||||
|
||||
override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
|
||||
return when (navTarget) {
|
||||
NavTarget.Root -> createNode<CreateRoomRootNode>(buildContext)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun View(modifier: Modifier) {
|
||||
Children(
|
||||
navModel = backstack,
|
||||
modifier = modifier,
|
||||
transitionHandler = rememberDefaultTransitionHandler()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package io.element.android.features.createroom.root
|
||||
|
||||
sealed interface CreateRoomRootEvents {
|
||||
object CreateRoom : CreateRoomRootEvents
|
||||
object InvitePeople : CreateRoomRootEvents
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package io.element.android.features.createroom.root
|
||||
|
||||
import android.os.Parcelable
|
||||
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.SessionScope
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
@ContributesNode(SessionScope::class)
|
||||
class CreateRoomRootNode @AssistedInject constructor(
|
||||
@Assisted buildContext: BuildContext,
|
||||
@Assisted plugins: List<Plugin>,
|
||||
private val presenter: CreateRoomRootPresenter,
|
||||
) : Node(buildContext, plugins = plugins) {
|
||||
|
||||
sealed interface NavTarget : Parcelable {
|
||||
@Parcelize
|
||||
object Root : NavTarget
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun View(modifier: Modifier) {
|
||||
val state = presenter.present()
|
||||
CreateRoomRootScreen(
|
||||
state = state,
|
||||
modifier = modifier,
|
||||
onClosePressed = this::navigateUp,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package io.element.android.features.createroom.root
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import javax.inject.Inject
|
||||
|
||||
class CreateRoomRootPresenter @Inject constructor() : Presenter<CreateRoomRootState> {
|
||||
|
||||
@Composable
|
||||
override fun present(): CreateRoomRootState {
|
||||
|
||||
fun handleEvents(event: CreateRoomRootEvents) {
|
||||
when (event) {
|
||||
CreateRoomRootEvents.CreateRoom -> Unit // Todo Handle create room action
|
||||
CreateRoomRootEvents.InvitePeople -> Unit // Todo Handle invite people action
|
||||
}
|
||||
}
|
||||
|
||||
return CreateRoomRootState(
|
||||
eventSink = ::handleEvents
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package io.element.android.features.createroom.root
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.SearchBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.CenterAlignedTopAppBar
|
||||
import io.element.android.libraries.designsystem.theme.components.DockedSearchBar
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.IconButton
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.R as DrawableR
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun CreateRoomRootScreen(
|
||||
state: CreateRoomRootState,
|
||||
modifier: Modifier = Modifier,
|
||||
onClosePressed: () -> Unit = {},
|
||||
) {
|
||||
var searchText by rememberSaveable { mutableStateOf("") }
|
||||
var isSearchActive by rememberSaveable { mutableStateOf(false) }
|
||||
Scaffold(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
topBar = {
|
||||
if (!isSearchActive) {
|
||||
CreateRoomRootViewTopBar(onClosePressed = onClosePressed)
|
||||
}
|
||||
}
|
||||
) { paddingValues ->
|
||||
Column(
|
||||
modifier = Modifier.padding(paddingValues),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
CreateRoomSearchBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = searchText,
|
||||
placeHolderTitle = stringResource(StringR.string.search_for_someone),
|
||||
active = isSearchActive,
|
||||
onActiveChanged = { isSearchActive = it },
|
||||
onTextChanged = { searchText = it },
|
||||
)
|
||||
|
||||
if (!isSearchActive) {
|
||||
CreateRoomActionButtonsList(
|
||||
onNewRoomClicked = { state.eventSink(CreateRoomRootEvents.CreateRoom) },
|
||||
onInvitePeopleClicked = { state.eventSink(CreateRoomRootEvents.InvitePeople) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun CreateRoomRootViewTopBar(
|
||||
modifier: Modifier = Modifier,
|
||||
onClosePressed: () -> Unit = {},
|
||||
) {
|
||||
CenterAlignedTopAppBar(
|
||||
modifier = modifier,
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(id = StringR.string.start_chat),
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
)
|
||||
},
|
||||
actions = {
|
||||
IconButton(onClick = onClosePressed) {
|
||||
Icon(imageVector = Icons.Default.Close, contentDescription = stringResource(id = StringR.string.action_close))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun CreateRoomSearchBar(
|
||||
text: String,
|
||||
placeHolderTitle: String,
|
||||
active: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
onActiveChanged: (Boolean) -> Unit = {},
|
||||
onTextChanged: (String) -> Unit = {},
|
||||
) {
|
||||
val focusManager = LocalFocusManager.current
|
||||
|
||||
if (!active) {
|
||||
onTextChanged("")
|
||||
focusManager.clearFocus()
|
||||
}
|
||||
|
||||
DockedSearchBar(
|
||||
query = text,
|
||||
onQueryChange = onTextChanged,
|
||||
onSearch = { focusManager.clearFocus() },
|
||||
active = active,
|
||||
onActiveChange = onActiveChanged,
|
||||
modifier = modifier
|
||||
.padding(horizontal = if (!active) 16.dp else 0.dp),
|
||||
placeholder = {
|
||||
Text(
|
||||
text = placeHolderTitle,
|
||||
modifier = Modifier.alpha(0.4f), // FIXME align on Design system theme (removing alpha should be fine)
|
||||
)
|
||||
},
|
||||
leadingIcon = if (active) {
|
||||
{ BackButton(onClick = { onActiveChanged(false) }) }
|
||||
} else null,
|
||||
trailingIcon = {
|
||||
if (active) {
|
||||
IconButton(onClick = { onTextChanged("") }) {
|
||||
Icon(Icons.Default.Close, stringResource(StringR.string.a11y_clear))
|
||||
}
|
||||
} else {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Search,
|
||||
contentDescription = stringResource(StringR.string.search),
|
||||
modifier = Modifier.alpha(0.4f), // FIXME align on Design system theme (removing alpha should be fine)
|
||||
)
|
||||
}
|
||||
},
|
||||
shape = if (!active) SearchBarDefaults.dockedShape else SearchBarDefaults.fullScreenShape,
|
||||
colors = if (!active) SearchBarDefaults.colors() else SearchBarDefaults.colors(containerColor = Color.Transparent),
|
||||
content = {},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CreateRoomActionButtonsList(
|
||||
modifier: Modifier = Modifier,
|
||||
onNewRoomClicked: () -> Unit = {},
|
||||
onInvitePeopleClicked: () -> Unit = {},
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
CreateRoomActionButton(
|
||||
iconRes = DrawableR.drawable.ic_groups,
|
||||
text = stringResource(id = StringR.string.new_room),
|
||||
onClick = onNewRoomClicked,
|
||||
)
|
||||
CreateRoomActionButton(
|
||||
iconRes = DrawableR.drawable.ic_share,
|
||||
text = stringResource(id = StringR.string.invite_people_menu),
|
||||
onClick = onInvitePeopleClicked,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CreateRoomActionButton(
|
||||
@DrawableRes iconRes: Int,
|
||||
text: String,
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: () -> Unit = {},
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 56.dp)
|
||||
.clickable { onClick() }
|
||||
.padding(horizontal = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.alpha(0.5f), // FIXME align on Design system theme (removing alpha should be fine)
|
||||
resourceId = iconRes,
|
||||
contentDescription = null,
|
||||
)
|
||||
Text(text = text)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CreateRoomRootViewLightPreview(@PreviewParameter(CreateRoomRootStateProvider::class) state: CreateRoomRootState) =
|
||||
ElementPreviewLight { ContentToPreview(state) }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CreateRoomRootViewDarkPreview(@PreviewParameter(CreateRoomRootStateProvider::class) state: CreateRoomRootState) =
|
||||
ElementPreviewDark { ContentToPreview(state) }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview(state: CreateRoomRootState) {
|
||||
CreateRoomRootScreen(
|
||||
state = state,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package io.element.android.features.createroom.root
|
||||
|
||||
// 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 CreateRoomRootState(
|
||||
val eventSink: (CreateRoomRootEvents) -> Unit
|
||||
)
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package io.element.android.features.createroom.root
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
|
||||
open class CreateRoomRootStateProvider : PreviewParameterProvider<CreateRoomRootState> {
|
||||
override val values: Sequence<CreateRoomRootState>
|
||||
get() = sequenceOf(
|
||||
aCreateRoomRootState(),
|
||||
// Add other state here
|
||||
)
|
||||
}
|
||||
|
||||
fun aCreateRoomRootState() = CreateRoomRootState(
|
||||
eventSink = {}
|
||||
)
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
||||
package io.element.android.features.createroom.root
|
||||
|
||||
import app.cash.molecule.RecompositionClock
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class CreateRoomRootPresenterTests {
|
||||
|
||||
@Test
|
||||
fun `present - initial state`() = runTest {
|
||||
val presenter = CreateRoomRootPresenter()
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - send event`() = runTest {
|
||||
val presenter = CreateRoomRootPresenter()
|
||||
moleculeFlow(RecompositionClock.Immediate) {
|
||||
presenter.present()
|
||||
}.test {
|
||||
val initialState = awaitItem()
|
||||
initialState.eventSink(CreateRoomRootEvents.CreateRoom) // Not implemented yet
|
||||
initialState.eventSink(CreateRoomRootEvents.InvitePeople) // Not implemented yet
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ import io.element.android.libraries.designsystem.components.form.textFieldState
|
|||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.LocalColors
|
||||
import io.element.android.libraries.designsystem.theme.components.BackButton
|
||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
|
|
@ -104,7 +104,7 @@ fun ChangeServerView(
|
|||
topBar = {
|
||||
TopAppBar(
|
||||
title = {},
|
||||
navigationIcon = { BackButton(action = onBackPressed, enabled = interactionEnabled) }
|
||||
navigationIcon = { BackButton(onClick = onBackPressed, enabled = interactionEnabled) }
|
||||
)
|
||||
}
|
||||
) { padding ->
|
||||
|
|
@ -192,7 +192,7 @@ fun ChangeServerView(
|
|||
IconButton(onClick = {
|
||||
homeserverFieldState = ""
|
||||
}, enabled = interactionEnabled) {
|
||||
Icon(imageVector = Icons.Filled.Close, contentDescription = stringResource(StringR.string.action_clear))
|
||||
Icon(imageVector = Icons.Filled.Close, contentDescription = stringResource(StringR.string.a11y_clear))
|
||||
}
|
||||
}
|
||||
} else null,
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ import io.element.android.libraries.designsystem.components.dialogs.ErrorDialog
|
|||
import io.element.android.libraries.designsystem.components.form.textFieldState
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.BackButton
|
||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||
import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
|
|
@ -101,7 +101,7 @@ fun LoginRootView(
|
|||
topBar = {
|
||||
TopAppBar(
|
||||
title = {},
|
||||
navigationIcon = { BackButton(action = onBackPressed, enabled = interactionEnabled) },
|
||||
navigationIcon = { BackButton(onClick = onBackPressed, enabled = interactionEnabled) },
|
||||
)
|
||||
}
|
||||
) { padding ->
|
||||
|
|
@ -267,7 +267,7 @@ internal fun LoginForm(
|
|||
IconButton(onClick = {
|
||||
loginFieldState = ""
|
||||
}) {
|
||||
Icon(imageVector = Icons.Filled.Close, contentDescription = stringResource(StringR.string.action_clear))
|
||||
Icon(imageVector = Icons.Filled.Close, contentDescription = stringResource(StringR.string.a11y_clear))
|
||||
}
|
||||
}
|
||||
} else null,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ interface RoomListEntryPoint : FeatureEntryPoint {
|
|||
|
||||
interface Callback : Plugin {
|
||||
fun onRoomClicked(roomId: RoomId)
|
||||
fun onCreateRoomClicked()
|
||||
fun onSettingsClicked()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ class RoomListNode @AssistedInject constructor(
|
|||
plugins<RoomListEntryPoint.Callback>().forEach { it.onSettingsClicked() }
|
||||
}
|
||||
|
||||
private fun onCreateRoomClicked() {
|
||||
plugins<RoomListEntryPoint.Callback>().forEach { it.onCreateRoomClicked() }
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun View(modifier: Modifier) {
|
||||
val state = presenter.present()
|
||||
|
|
@ -51,7 +55,8 @@ class RoomListNode @AssistedInject constructor(
|
|||
state = state,
|
||||
modifier = modifier,
|
||||
onRoomClicked = this::onRoomClicked,
|
||||
onOpenSettings = this::onOpenSettings
|
||||
onOpenSettings = this::onOpenSettings,
|
||||
onCreateRoomClicked = this::onCreateRoomClicked,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.rememberTopAppBarState
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -31,6 +32,7 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.unit.Velocity
|
||||
|
|
@ -39,11 +41,15 @@ import io.element.android.features.roomlist.impl.components.RoomSummaryRow
|
|||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.designsystem.theme.components.FloatingActionButton
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||
import io.element.android.libraries.designsystem.utils.LogCompositions
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.ui.model.MatrixUser
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import io.element.android.libraries.designsystem.R as DrawableR
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@Composable
|
||||
fun RoomListView(
|
||||
|
|
@ -51,6 +57,7 @@ fun RoomListView(
|
|||
modifier: Modifier = Modifier,
|
||||
onRoomClicked: (RoomId) -> Unit = {},
|
||||
onOpenSettings: () -> Unit = {},
|
||||
onCreateRoomClicked: () -> Unit = {},
|
||||
) {
|
||||
fun onFilterChanged(filter: String) {
|
||||
state.eventSink(RoomListEvents.UpdateFilter(filter))
|
||||
|
|
@ -69,6 +76,7 @@ fun RoomListView(
|
|||
onFilterChanged = ::onFilterChanged,
|
||||
onOpenSettings = onOpenSettings,
|
||||
onScrollOver = ::onVisibleRangedChanged,
|
||||
onCreateRoomClicked = onCreateRoomClicked,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -83,6 +91,7 @@ fun RoomListContent(
|
|||
onFilterChanged: (String) -> Unit = {},
|
||||
onOpenSettings: () -> Unit = {},
|
||||
onScrollOver: (IntRange) -> Unit = {},
|
||||
onCreateRoomClicked: () -> Unit = {},
|
||||
) {
|
||||
fun onRoomClicked(room: RoomListRoomSummary) {
|
||||
onRoomClicked(room.roomId)
|
||||
|
|
@ -145,7 +154,16 @@ fun RoomListContent(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
floatingActionButton = {
|
||||
FloatingActionButton(
|
||||
// FIXME align on Design system theme
|
||||
containerColor = MaterialTheme.colorScheme.primary,
|
||||
onClick = onCreateRoomClicked
|
||||
) {
|
||||
Icon(resourceId = DrawableR.drawable.ic_edit_square, contentDescription = stringResource(id = StringR.string.a11y_create_message))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.theme.components
|
||||
package io.element.android.libraries.designsystem.components.button
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.material.icons.Icons
|
||||
|
|
@ -26,22 +26,24 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
import io.element.android.libraries.ui.strings.R.string as StringR
|
||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||
import io.element.android.libraries.designsystem.theme.components.IconButton
|
||||
import io.element.android.libraries.ui.strings.R as StringR
|
||||
|
||||
@Composable
|
||||
fun BackButton(
|
||||
action: () -> Unit,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
icon: ImageVector = Icons.Default.ArrowBack,
|
||||
contentDescription: String = stringResource(StringR.action_back),
|
||||
imageVector: ImageVector = Icons.Default.ArrowBack,
|
||||
contentDescription: String = stringResource(StringR.string.a11y_back),
|
||||
enabled: Boolean = true
|
||||
) {
|
||||
IconButton(
|
||||
modifier = modifier,
|
||||
onClick = action,
|
||||
onClick = onClick,
|
||||
enabled = enabled,
|
||||
) {
|
||||
Icon(imageVector = icon, contentDescription = contentDescription)
|
||||
Icon(imageVector = imageVector, contentDescription = contentDescription)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -56,7 +58,7 @@ internal fun BackButtonPreviewDark() = ElementPreviewDark { ContentToPreview() }
|
|||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
Column {
|
||||
BackButton(action = { }, enabled = true, contentDescription = "Back")
|
||||
BackButton(action = { }, enabled = false, contentDescription = "Back")
|
||||
BackButton(onClick = { }, enabled = true, contentDescription = "Back")
|
||||
BackButton(onClick = { }, enabled = false, contentDescription = "Back")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package io.element.android.libraries.designsystem.theme.components
|
||||
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.TopAppBarColors
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun CenterAlignedTopAppBar(
|
||||
title: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
navigationIcon: @Composable () -> Unit = {},
|
||||
actions: @Composable RowScope.() -> Unit = {},
|
||||
windowInsets: WindowInsets = TopAppBarDefaults.windowInsets,
|
||||
colors: TopAppBarColors = TopAppBarDefaults.centerAlignedTopAppBarColors(),
|
||||
scrollBehavior: TopAppBarScrollBehavior? = null,
|
||||
) {
|
||||
androidx.compose.material3.CenterAlignedTopAppBar(
|
||||
title = title,
|
||||
modifier = modifier,
|
||||
navigationIcon = navigationIcon,
|
||||
actions = actions,
|
||||
windowInsets = windowInsets,
|
||||
colors = colors,
|
||||
scrollBehavior = scrollBehavior,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun CenterAlignedTopAppBarLightPreview() =
|
||||
ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun CenterAlignedTopAppBarDarkPreview() =
|
||||
ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
CenterAlignedTopAppBar(title = { Text(text = "Title") })
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package io.element.android.libraries.designsystem.theme.components
|
||||
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.SearchBarColors
|
||||
import androidx.compose.material3.SearchBarDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun DockedSearchBar(
|
||||
query: String,
|
||||
onQueryChange: (String) -> Unit,
|
||||
onSearch: (String) -> Unit,
|
||||
active: Boolean,
|
||||
onActiveChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
placeholder: @Composable (() -> Unit)? = null,
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
trailingIcon: @Composable (() -> Unit)? = null,
|
||||
shape: Shape = SearchBarDefaults.dockedShape,
|
||||
colors: SearchBarColors = SearchBarDefaults.colors(),
|
||||
tonalElevation: Dp = SearchBarDefaults.Elevation,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
content: @Composable ColumnScope.() -> Unit,
|
||||
) {
|
||||
androidx.compose.material3.DockedSearchBar(
|
||||
query = query,
|
||||
onQueryChange = onQueryChange,
|
||||
onSearch = onSearch,
|
||||
active = active,
|
||||
onActiveChange = onActiveChange,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
placeholder = placeholder,
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon,
|
||||
shape = shape,
|
||||
colors = colors,
|
||||
tonalElevation = tonalElevation,
|
||||
interactionSource = interactionSource,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun DockedSearchBarLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun DockedSearchBarDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
DockedSearchBar(
|
||||
query = "Some text",
|
||||
onQueryChange = {},
|
||||
onSearch = {},
|
||||
active = false,
|
||||
onActiveChange = {},
|
||||
content = {},
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.designsystem.theme.components
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.material3.ButtonColors
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.ButtonElevation
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||
|
||||
@Composable
|
||||
fun TextButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
shape: Shape = ButtonDefaults.textShape,
|
||||
colors: ButtonColors = ButtonDefaults.textButtonColors(),
|
||||
elevation: ButtonElevation? = null,
|
||||
border: BorderStroke? = null,
|
||||
contentPadding: PaddingValues = ButtonDefaults.TextButtonContentPadding,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
content: @Composable RowScope.() -> Unit
|
||||
) {
|
||||
androidx.compose.material3.TextButton(
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
shape = shape,
|
||||
colors = colors,
|
||||
elevation = elevation,
|
||||
border = border,
|
||||
contentPadding = contentPadding,
|
||||
interactionSource = interactionSource,
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun TextButtonLightPreview() = ElementPreviewLight { ContentToPreview() }
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
internal fun TextButtonDarkPreview() = ElementPreviewDark { ContentToPreview() }
|
||||
|
||||
@Composable
|
||||
private fun ContentToPreview() {
|
||||
Column {
|
||||
TextButton(onClick = {}, enabled = true) {
|
||||
Text(text = "Click me! - Enabled")
|
||||
}
|
||||
TextButton(onClick = {}, enabled = false) {
|
||||
Text(text = "Click me! - Disabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<!--
|
||||
~ Copyright (c) 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.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:tint="#000000"
|
||||
android:width="21dp"
|
||||
android:height="22dp"
|
||||
android:viewportWidth="21"
|
||||
android:viewportHeight="22">
|
||||
<path
|
||||
android:pathData="M1.5,21.7C1.1,21.7 0.75,21.55 0.45,21.25C0.15,20.95 0,20.6 0,20.2V5.2C0,4.8 0.15,4.45 0.45,4.15C0.75,3.85 1.1,3.7 1.5,3.7H11.625L10.125,5.2H1.5V20.2H16.5V11.5L18,10V20.2C18,20.6 17.85,20.95 17.55,21.25C17.25,21.55 16.9,21.7 16.5,21.7H1.5ZM13.55,3.9L14.625,4.95L7.5,12.05V14.2H9.625L16.775,7.05L17.825,8.1L10.7,15.25C10.567,15.383 10.404,15.492 10.212,15.575C10.021,15.658 9.825,15.7 9.625,15.7H6.75C6.533,15.7 6.354,15.629 6.213,15.488C6.071,15.346 6,15.167 6,14.95V12.075C6,11.875 6.042,11.679 6.125,11.488C6.208,11.296 6.317,11.133 6.45,11L13.55,3.9ZM17.825,8.1L13.55,3.9L16.05,1.4C16.333,1.117 16.688,0.975 17.112,0.975C17.538,0.975 17.892,1.125 18.175,1.425L20.275,3.55C20.558,3.85 20.7,4.204 20.7,4.613C20.7,5.021 20.55,5.367 20.25,5.65L17.825,8.1Z"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
||||
25
libraries/designsystem/src/main/res/drawable/ic_groups.xml
Normal file
25
libraries/designsystem/src/main/res/drawable/ic_groups.xml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<!--
|
||||
~ Copyright (c) 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.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/black"
|
||||
android:pathData="M1.365,17.788C1.12,17.788 0.915,17.705 0.749,17.54C0.583,17.374 0.5,17.168 0.5,16.923V16.569C0.5,15.894 0.844,15.346 1.531,14.927C2.219,14.508 3.126,14.298 4.251,14.298C4.454,14.298 4.647,14.305 4.829,14.318C5.011,14.332 5.187,14.355 5.358,14.389C5.168,14.681 5.028,14.995 4.94,15.332C4.852,15.668 4.808,16.024 4.808,16.4V17.788H1.365ZM7.408,17.788C7.147,17.788 6.931,17.702 6.759,17.529C6.586,17.355 6.5,17.141 6.5,16.885V16.438C6.5,15.483 7.006,14.713 8.018,14.128C9.03,13.543 10.356,13.25 11.996,13.25C13.651,13.25 14.982,13.543 15.989,14.128C16.996,14.713 17.5,15.483 17.5,16.438V16.885C17.5,17.141 17.413,17.355 17.24,17.529C17.067,17.702 16.852,17.788 16.596,17.788H7.408ZM19.192,17.788V16.4C19.192,16.024 19.145,15.668 19.05,15.332C18.955,14.995 18.819,14.681 18.642,14.389C18.813,14.355 18.989,14.332 19.17,14.318C19.352,14.305 19.545,14.298 19.75,14.298C20.875,14.298 21.781,14.508 22.469,14.927C23.156,15.346 23.5,15.894 23.5,16.569V16.923C23.5,17.168 23.417,17.374 23.251,17.54C23.085,17.705 22.88,17.788 22.635,17.788H19.192ZM12,14.75C10.954,14.75 10.059,14.892 9.315,15.176C8.572,15.46 8.159,15.799 8.077,16.192V16.288H15.923V16.192C15.831,15.788 15.415,15.447 14.677,15.168C13.938,14.889 13.046,14.75 12,14.75ZM4.25,13.327C3.777,13.327 3.375,13.159 3.044,12.824C2.713,12.489 2.548,12.086 2.548,11.615C2.548,11.145 2.713,10.742 3.044,10.407C3.375,10.071 3.777,9.904 4.25,9.904C4.723,9.904 5.127,10.071 5.461,10.407C5.794,10.742 5.961,11.145 5.961,11.615C5.961,12.086 5.794,12.489 5.459,12.824C5.124,13.159 4.721,13.327 4.25,13.327ZM19.75,13.327C19.277,13.327 18.873,13.159 18.539,12.824C18.205,12.489 18.038,12.086 18.038,11.615C18.038,11.145 18.206,10.742 18.541,10.407C18.876,10.071 19.279,9.904 19.75,9.904C20.223,9.904 20.625,10.071 20.956,10.407C21.286,10.742 21.452,11.145 21.452,11.615C21.452,12.086 21.286,12.489 20.956,12.824C20.625,13.159 20.223,13.327 19.75,13.327ZM12,12.5C11.279,12.5 10.666,12.248 10.161,11.743C9.656,11.238 9.404,10.625 9.404,9.904C9.404,9.183 9.656,8.57 10.161,8.065C10.666,7.56 11.279,7.308 12,7.308C12.721,7.308 13.334,7.56 13.839,8.065C14.344,8.57 14.596,9.183 14.596,9.904C14.596,10.625 14.344,11.238 13.839,11.743C13.334,12.248 12.721,12.5 12,12.5ZM12.002,8.808C11.691,8.808 11.431,8.913 11.22,9.122C11.009,9.332 10.904,9.592 10.904,9.902C10.904,10.212 11.009,10.473 11.218,10.684C11.428,10.895 11.688,11 11.998,11C12.308,11 12.569,10.895 12.78,10.685C12.991,10.476 13.096,10.216 13.096,9.906C13.096,9.595 12.991,9.335 12.781,9.124C12.572,8.913 12.312,8.808 12.002,8.808Z" />
|
||||
</vector>
|
||||
25
libraries/designsystem/src/main/res/drawable/ic_share.xml
Normal file
25
libraries/designsystem/src/main/res/drawable/ic_share.xml
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<!--
|
||||
~ Copyright (c) 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.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/black"
|
||||
android:pathData="M18.001,21.75C17.237,21.75 16.588,21.483 16.053,20.948C15.518,20.413 15.25,19.764 15.25,19C15.25,18.875 15.26,18.746 15.28,18.612C15.3,18.478 15.33,18.355 15.369,18.242L7.973,13.911C7.709,14.174 7.408,14.38 7.071,14.528C6.734,14.676 6.377,14.75 6,14.75C5.236,14.75 4.587,14.483 4.052,13.948C3.517,13.414 3.25,12.765 3.25,12.001C3.25,11.238 3.517,10.588 4.052,10.053C4.587,9.518 5.236,9.25 6,9.25C6.377,9.25 6.734,9.324 7.071,9.472C7.408,9.62 7.709,9.826 7.973,10.089L15.369,5.758C15.33,5.645 15.3,5.522 15.28,5.388C15.26,5.254 15.25,5.125 15.25,5C15.25,4.236 15.517,3.587 16.052,3.052C16.586,2.517 17.235,2.25 17.999,2.25C18.762,2.25 19.412,2.517 19.947,3.052C20.482,3.586 20.75,4.235 20.75,4.999C20.75,5.762 20.483,6.412 19.948,6.947C19.413,7.482 18.764,7.75 18,7.75C17.623,7.75 17.266,7.676 16.929,7.528C16.592,7.38 16.291,7.174 16.027,6.912L8.631,11.242C8.67,11.355 8.7,11.478 8.72,11.611C8.74,11.745 8.75,11.874 8.75,11.998C8.75,12.122 8.74,12.252 8.72,12.387C8.7,12.521 8.67,12.645 8.631,12.758L16.027,17.088C16.291,16.826 16.592,16.62 16.929,16.472C17.266,16.324 17.623,16.25 18,16.25C18.764,16.25 19.413,16.517 19.948,17.052C20.483,17.586 20.75,18.235 20.75,18.999C20.75,19.762 20.483,20.412 19.948,20.947C19.414,21.482 18.765,21.75 18.001,21.75ZM18,6.25C18.347,6.25 18.643,6.129 18.886,5.886C19.128,5.643 19.25,5.347 19.25,5C19.25,4.653 19.128,4.357 18.886,4.114C18.643,3.871 18.347,3.75 18,3.75C17.653,3.75 17.357,3.871 17.114,4.114C16.871,4.357 16.75,4.653 16.75,5C16.75,5.347 16.871,5.643 17.114,5.886C17.357,6.129 17.653,6.25 18,6.25ZM6,13.25C6.347,13.25 6.643,13.128 6.886,12.886C7.129,12.643 7.25,12.347 7.25,12C7.25,11.653 7.129,11.357 6.886,11.114C6.643,10.871 6.347,10.75 6,10.75C5.653,10.75 5.357,10.871 5.114,11.114C4.871,11.357 4.75,11.653 4.75,12C4.75,12.347 4.871,12.643 5.114,12.886C5.357,13.128 5.653,13.25 6,13.25ZM18,20.25C18.347,20.25 18.643,20.128 18.886,19.886C19.128,19.643 19.25,19.347 19.25,19C19.25,18.653 19.128,18.357 18.886,18.114C18.643,17.871 18.347,17.75 18,17.75C17.653,17.75 17.357,17.871 17.114,18.114C16.871,18.357 16.75,18.653 16.75,19C16.75,19.347 16.871,19.643 17.114,19.886C17.357,20.128 17.653,20.25 18,20.25Z" />
|
||||
</vector>
|
||||
|
|
@ -2,17 +2,20 @@
|
|||
<resources>
|
||||
|
||||
<!-- Add new strings for Element X Android here -->
|
||||
<string name="action_back">Back</string>
|
||||
<string name="action_clear">Clear</string>
|
||||
|
||||
<!-- Common -->
|
||||
<string name="a11y_back">Back</string>
|
||||
<string name="a11y_clear">Clear</string>
|
||||
<!-- Login -->
|
||||
<string name="login_form_title">Enter your details</string>
|
||||
<string name="ex_login_username_hint">Email or username</string>
|
||||
<string name="login_show_password">Show password</string>
|
||||
<string name="login_hide_password">Hide password</string>
|
||||
|
||||
<string name="ex_choose_server_subtitle">What is the address of your server?</string>
|
||||
<string name="server_selection_server_footer">You can only connect to an existing server that supports sliding sync. Your homeserver admin will need to configure it.</string>
|
||||
<string name="server_selection_sliding_sync_alert_title">Server not supported</string>
|
||||
<string name="server_selection_sliding_sync_alert_message">This server currently doesn\'t support sliding sync.</string>
|
||||
<!-- Create room -->
|
||||
<string name="search_for_someone">Search for someone</string>
|
||||
<string name="new_room">New room</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,9 @@ fun DependencyHandlerScope.composeDependencies(libs: LibrariesForLibs) {
|
|||
androidTestImplementation(composeBom)
|
||||
implementation("androidx.compose.ui:ui")
|
||||
implementation("androidx.compose.material:material")
|
||||
implementation("androidx.compose.material3:material3")
|
||||
// Override BOM version, SearchBar is not available in the actual version
|
||||
// do not use latest version because of clashes on androidx lifecycle dependency
|
||||
implementation("androidx.compose.material3:material3:1.1.0-alpha04")
|
||||
implementation("androidx.compose.material:material-icons-extended")
|
||||
implementation("androidx.compose.ui:ui-tooling-preview")
|
||||
implementation("androidx.activity:activity-compose:1.6.1")
|
||||
|
|
@ -67,4 +69,5 @@ fun DependencyHandlerScope.allFeatures() {
|
|||
implementation(project(":features:messages:impl"))
|
||||
implementation(project(":features:rageshake:impl"))
|
||||
implementation(project(":features:preferences:impl"))
|
||||
implementation(project(":features:createroom"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,3 +80,4 @@ include(":features:messages:api")
|
|||
include(":features:messages:impl")
|
||||
include(":features:login:api")
|
||||
include(":features:login:impl")
|
||||
include(":features:createroom")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:510c17406a13ce64a9b7578d70535dac7fe20e9c3a9a4ab3c8cab775bc46f568
|
||||
size 19718
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:611b1efa9cf46316f96738130f326061595d2648ac7fb059df299e7c95f4e2a8
|
||||
size 18480
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3460e8f37e746e0ae7a30c1a055a3b68cc013197c4f2567d19ad51c00f8d6385
|
||||
size 34814
|
||||
oid sha256:a339ab789eb6710aa5edba53acc46a61de373566089590940ab4c8233e97558b
|
||||
size 34721
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f86089af6c02e8eb4811ae0092150c2d5e439731ae970e7954a66fca7f98fd11
|
||||
size 34173
|
||||
oid sha256:675c1cbfc80acec11434153dacb1d69b0cf6122fb068db8a92ae86e039a54c71
|
||||
size 34091
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b21168d83ed8d7c116e72dd76292975530f1c898ef32502aa382f292aef4f8aa
|
||||
size 30951
|
||||
oid sha256:8137f8ed97a1a924fc76e16c8f0f0fc5a4a866d989460859b98edfcb5c7f98b7
|
||||
size 30996
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3460e8f37e746e0ae7a30c1a055a3b68cc013197c4f2567d19ad51c00f8d6385
|
||||
size 34814
|
||||
oid sha256:a339ab789eb6710aa5edba53acc46a61de373566089590940ab4c8233e97558b
|
||||
size 34721
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f81c7b793611e5f3f975245bf5ba52d59bf5725519292f05dd7840c2e38d3166
|
||||
size 33237
|
||||
oid sha256:04f73ec1830baa28808881f040f6bfc2b1ce0de1ca2d4b3e16a3b57513814a7f
|
||||
size 33173
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:04c34dbc9fe2df9af3133e1b7c444d58e7d8a35161a97155c384dceac28ee698
|
||||
size 32324
|
||||
oid sha256:da84d9195ed0cac06efff562156ed8abc161a6dbd3272727c1cb787b83c62558
|
||||
size 32253
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:922ee759a8e4b689ced8ade809c651464956395ffc0a2b3d9025f067a9807aa9
|
||||
size 30066
|
||||
oid sha256:ea2dce0fde5ff6563f283e643edadd5c95c29a4084c8f1d3902ec3c759cccea7
|
||||
size 30070
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f81c7b793611e5f3f975245bf5ba52d59bf5725519292f05dd7840c2e38d3166
|
||||
size 33237
|
||||
oid sha256:04f73ec1830baa28808881f040f6bfc2b1ce0de1ca2d4b3e16a3b57513814a7f
|
||||
size 33173
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:81905bde677949780ef6c850be8dde97c88895b82d83414589e07f0725064050
|
||||
size 13530
|
||||
oid sha256:ff04bf07f8c24b3b19d4926bb3c51b257166befe062fe8b8012d2e92dbfe3491
|
||||
size 13477
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:edd3b0f29a3fbf9035cc8ba1d7a5a3a74be30d4e6ec8f654832f7ee916497453
|
||||
size 12457
|
||||
oid sha256:e50325c75193e47958862ea9cb515d7c84d2c47a00b01256fc244319780c107f
|
||||
size 12425
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3764d8bd7dc2783a8af43aad65a217d7e533ed17c4d4367b7994470bf35b62b0
|
||||
size 4462
|
||||
oid sha256:328963ebd74fbbe47fd4a4d1f0edce5bf014d88a266c114e50a5274e87a88fe8
|
||||
size 7154
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:3764d8bd7dc2783a8af43aad65a217d7e533ed17c4d4367b7994470bf35b62b0
|
||||
size 4462
|
||||
oid sha256:007fd7051cb4b8059dc33ff1cd2b4be4cffaa5e1c129adb61dd4d9e8a561953f
|
||||
size 7096
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a50e661d6c3c45574fa3d6fc64b0d5f2a1c9dbba18a77be900df1dfce9df1f69
|
||||
size 35103
|
||||
oid sha256:3c8868d4974f23637afed9ecd062b88421e2b39ffe22f19742b946afc91caeb6
|
||||
size 37838
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7d27f9fbe2b6d803198f0015cc391d6dfdd5d2708e837319c6eb0e82f8ab832c
|
||||
size 33488
|
||||
oid sha256:43b69859fa3ee38d2b7f7415b87738db65dc6dac3d2fabddc1f1346b0b64932b
|
||||
size 37329
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:17b110e460f4212927c46d593352dac88493bb7be9a5d2ae8b4e0b8e6c79d0bf
|
||||
size 5695
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:29c30e97a5c1de9e855001c6f27322bce8795954ac5c134c34ea3c9de417acd2
|
||||
size 5250
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b662595580f6e0dd4ff6722fc0c8db63b0811a615a41356ba6b28d22285b6765
|
||||
size 5813
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b8a9745199ef10a4e0c8e101203ce51999449b7c43bf8b764f162ea975ebaefe
|
||||
size 5548
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:e89807d72107f1f8337e8de803791249b56bde6c4961805520195ea55563749a
|
||||
size 8470
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:6381c125b8eaf6b116218bc4b0efda4866f19514139f4b45604909e462931c1f
|
||||
size 8320
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fde95a558052ae09123d459249e9b2d8ba3a3f6adb1bba4002ac0aca90d5b657
|
||||
size 11668
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:81be7efc599fbe85a373aecfe85047f521ad609ce6b85b343386bb101aaddb68
|
||||
size 10611
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a796bba1f316b03793b415d109940940a6d81a924f55a745764bb6ec46cab40b
|
||||
size 39585
|
||||
oid sha256:03bfd855f6e010d2d4dc0cb9f3c13e76a4f2bbcda98b086dabcd33f201ebe10a
|
||||
size 39486
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5386114bbb3cbf6c8a3de0642f1efa7a3b5d7efa46168d70aeffc413e37ec803
|
||||
size 39014
|
||||
oid sha256:29bbaae8c846dfe05bb66e08debeb84422d45f88982f79faefb94f332843c26e
|
||||
size 39069
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue