Creation wizard WIP
This commit is contained in:
parent
d8a3229819
commit
4b27ad8ba6
|
@ -274,6 +274,7 @@
|
|||
<activity android:name=".features.devtools.RoomDevToolActivity"/>
|
||||
<activity android:name=".features.spaces.SpacePreviewActivity"/>
|
||||
<activity android:name=".features.spaces.SpaceExploreActivity"/>
|
||||
<activity android:name=".features.spaces.SpaceCreationActivity"/>
|
||||
<!-- Services -->
|
||||
|
||||
<service
|
||||
|
|
|
@ -118,6 +118,9 @@ import im.vector.app.features.settings.threepids.ThreePidsSettingsFragment
|
|||
import im.vector.app.features.share.IncomingShareFragment
|
||||
import im.vector.app.features.signout.soft.SoftLogoutFragment
|
||||
import im.vector.app.features.spaces.SpaceListFragment
|
||||
import im.vector.app.features.spaces.create.ChooseSpaceTypeFragment
|
||||
import im.vector.app.features.spaces.create.CreateSpaceDefaultRoomsFragment
|
||||
import im.vector.app.features.spaces.create.CreateSpaceDetailsFragment
|
||||
import im.vector.app.features.spaces.preview.SpacePreviewFragment
|
||||
import im.vector.app.features.terms.ReviewTermsFragment
|
||||
import im.vector.app.features.usercode.ShowUserCodeFragment
|
||||
|
@ -636,4 +639,19 @@ interface FragmentModule {
|
|||
@IntoMap
|
||||
@FragmentKey(SpacePreviewFragment::class)
|
||||
fun bindSpacePreviewFragment(fragment: SpacePreviewFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(ChooseSpaceTypeFragment::class)
|
||||
fun bindCreateSpaceFragment(fragment: ChooseSpaceTypeFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(CreateSpaceDetailsFragment::class)
|
||||
fun bindCreateSpaceDetailsFragment(fragment: CreateSpaceDetailsFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(CreateSpaceDefaultRoomsFragment::class)
|
||||
fun bindCreateSpaceDefaultRoomsFragment(fragment: CreateSpaceDefaultRoomsFragment): Fragment
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ import im.vector.app.features.settings.VectorSettingsActivity
|
|||
import im.vector.app.features.settings.devices.DeviceVerificationInfoBottomSheet
|
||||
import im.vector.app.features.share.IncomingShareActivity
|
||||
import im.vector.app.features.signout.soft.SoftLogoutActivity
|
||||
import im.vector.app.features.spaces.SpaceCreationActivity
|
||||
import im.vector.app.features.terms.ReviewTermsActivity
|
||||
import im.vector.app.features.ui.UiStateRepository
|
||||
import im.vector.app.features.usercode.UserCodeActivity
|
||||
|
@ -151,6 +152,7 @@ interface ScreenComponent {
|
|||
fun inject(activity: CallTransferActivity)
|
||||
fun inject(activity: ReAuthActivity)
|
||||
fun inject(activity: RoomDevToolActivity)
|
||||
fun inject(activity: SpaceCreationActivity)
|
||||
|
||||
/* ==========================================================================================
|
||||
* BottomSheets
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (c) 2020 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 im.vector.app.features.form
|
||||
|
||||
import android.net.Uri
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import com.airbnb.epoxy.EpoxyModelWithHolder
|
||||
import com.bumptech.glide.request.RequestOptions
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.ClickListener
|
||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.app.core.epoxy.onClick
|
||||
import im.vector.app.core.glide.GlideApp
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
|
||||
@EpoxyModelClass(layout = R.layout.item_editable_square_avatar)
|
||||
abstract class FormEditableSquareAvatarItem : EpoxyModelWithHolder<FormEditableSquareAvatarItem.Holder>() {
|
||||
|
||||
@EpoxyAttribute
|
||||
var avatarRenderer: AvatarRenderer? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var matrixItem: MatrixItem? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var enabled: Boolean = true
|
||||
|
||||
@EpoxyAttribute
|
||||
var imageUri: Uri? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var clickListener: ClickListener? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var deleteListener: ClickListener? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
holder.imageContainer.onClick(clickListener?.takeIf { enabled })
|
||||
if (matrixItem != null) {
|
||||
avatarRenderer?.renderSpace(matrixItem!!, holder.image)
|
||||
} else {
|
||||
GlideApp.with(holder.image)
|
||||
.load(imageUri)
|
||||
.apply(RequestOptions.circleCropTransform())
|
||||
.into(holder.image)
|
||||
}
|
||||
holder.delete.isVisible = enabled && (imageUri != null || matrixItem?.avatarUrl?.isNotEmpty() == true)
|
||||
holder.delete.onClick(deleteListener?.takeIf { enabled })
|
||||
}
|
||||
|
||||
override fun unbind(holder: Holder) {
|
||||
avatarRenderer?.clear(holder.image)
|
||||
GlideApp.with(holder.image).clear(holder.image)
|
||||
super.unbind(holder)
|
||||
}
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val imageContainer by bind<View>(R.id.itemEditableAvatarImageContainer)
|
||||
val image by bind<ImageView>(R.id.itemEditableAvatarImage)
|
||||
val delete by bind<View>(R.id.itemEditableAvatarDelete)
|
||||
}
|
||||
}
|
|
@ -54,6 +54,7 @@ import im.vector.app.features.popup.VerificationVectorAlert
|
|||
import im.vector.app.features.rageshake.VectorUncaughtExceptionHandler
|
||||
import im.vector.app.features.settings.VectorPreferences
|
||||
import im.vector.app.features.settings.VectorSettingsActivity
|
||||
import im.vector.app.features.spaces.SpaceCreationActivity
|
||||
import im.vector.app.features.spaces.SpacePreviewActivity
|
||||
import im.vector.app.features.themes.ThemeUtils
|
||||
import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
|
||||
|
@ -145,6 +146,9 @@ class HomeActivity :
|
|||
is HomeActivitySharedAction.OpenSpacePreview -> {
|
||||
startActivity(SpacePreviewActivity.newIntent(this, sharedAction.spaceId))
|
||||
}
|
||||
is HomeActivitySharedAction.AddSpace -> {
|
||||
startActivity(SpaceCreationActivity.newIntent(this))
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
.disposeOnDestroy()
|
||||
|
|
|
@ -25,5 +25,6 @@ sealed class HomeActivitySharedAction : VectorSharedAction {
|
|||
object OpenDrawer : HomeActivitySharedAction()
|
||||
object CloseDrawer : HomeActivitySharedAction()
|
||||
object OpenGroup : HomeActivitySharedAction()
|
||||
object AddSpace : HomeActivitySharedAction()
|
||||
data class OpenSpacePreview(val spaceId: String) : HomeActivitySharedAction()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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 im.vector.app.features.spaces
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.MenuItem
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.airbnb.mvrx.viewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.ScreenComponent
|
||||
import im.vector.app.core.extensions.toMvRxBundle
|
||||
import im.vector.app.core.platform.SimpleFragmentActivity
|
||||
import im.vector.app.features.spaces.create.ChooseSpaceTypeFragment
|
||||
import im.vector.app.features.spaces.create.CreateSpaceAction
|
||||
import im.vector.app.features.spaces.create.CreateSpaceDefaultRoomsFragment
|
||||
import im.vector.app.features.spaces.create.CreateSpaceDetailsFragment
|
||||
import im.vector.app.features.spaces.create.CreateSpaceEvents
|
||||
import im.vector.app.features.spaces.create.CreateSpaceState
|
||||
import im.vector.app.features.spaces.create.CreateSpaceViewModel
|
||||
import javax.inject.Inject
|
||||
|
||||
class SpaceCreationActivity : SimpleFragmentActivity(), CreateSpaceViewModel.Factory {
|
||||
|
||||
@Inject lateinit var viewModelFactory: CreateSpaceViewModel.Factory
|
||||
|
||||
override fun injectWith(injector: ScreenComponent) {
|
||||
super.injectWith(injector)
|
||||
injector.inject(this)
|
||||
}
|
||||
|
||||
val viewModel: CreateSpaceViewModel by viewModel()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
if (isFirstCreation()) {
|
||||
when (withState(viewModel) { it.step }) {
|
||||
CreateSpaceState.Step.ChooseType -> {
|
||||
navigateToFragment(ChooseSpaceTypeFragment::class.java)
|
||||
}
|
||||
CreateSpaceState.Step.SetDetails -> {
|
||||
navigateToFragment(ChooseSpaceTypeFragment::class.java)
|
||||
}
|
||||
CreateSpaceState.Step.AddRooms -> TODO()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (item.itemId == android.R.id.home) {
|
||||
onBackPressed()
|
||||
return true
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun initUiAndData() {
|
||||
super.initUiAndData()
|
||||
viewModel.subscribe(this) {
|
||||
renderState(it)
|
||||
}
|
||||
|
||||
viewModel.observeViewEvents {
|
||||
when (it) {
|
||||
CreateSpaceEvents.NavigateToDetails -> {
|
||||
navigateToFragment(CreateSpaceDetailsFragment::class.java)
|
||||
}
|
||||
CreateSpaceEvents.NavigateToChooseType -> {
|
||||
navigateToFragment(ChooseSpaceTypeFragment::class.java)
|
||||
}
|
||||
CreateSpaceEvents.Dismiss -> {
|
||||
finish()
|
||||
}
|
||||
CreateSpaceEvents.NavigateToAddRooms -> {
|
||||
navigateToFragment(CreateSpaceDefaultRoomsFragment::class.java)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun navigateToFragment(fragmentClass: Class<out Fragment>) {
|
||||
val frag = supportFragmentManager.findFragmentByTag(fragmentClass.name) ?: createFragment(fragmentClass, Bundle().toMvRxBundle())
|
||||
supportFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(R.anim.fade_in, R.anim.fade_out, R.anim.fade_in, R.anim.fade_out)
|
||||
.replace(R.id.container,
|
||||
frag,
|
||||
fragmentClass.name
|
||||
)
|
||||
.commit()
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
viewModel.handle(CreateSpaceAction.OnBackPressed)
|
||||
}
|
||||
|
||||
private fun renderState(state: CreateSpaceState) {
|
||||
val titleRes = when (state.step) {
|
||||
CreateSpaceState.Step.ChooseType -> R.string.activity_create_space_title
|
||||
CreateSpaceState.Step.SetDetails -> R.string.your_public_space
|
||||
CreateSpaceState.Step.AddRooms -> R.string.your_public_space
|
||||
}
|
||||
supportActionBar?.let {
|
||||
it.title = getString(titleRes)
|
||||
} ?: run {
|
||||
setTitle(getString(titleRes))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun newIntent(context: Context): Intent {
|
||||
return Intent(context, SpaceCreationActivity::class.java).apply {
|
||||
// putExtra(MvRx.KEY_ARG, SpaceDirectoryArgs(spaceId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun create(initialState: CreateSpaceState): CreateSpaceViewModel = viewModelFactory.create(initialState)
|
||||
}
|
|
@ -57,6 +57,7 @@ class SpaceListFragment @Inject constructor(
|
|||
when (it) {
|
||||
is SpaceListViewEvents.OpenSpaceSummary -> sharedActionViewModel.post(HomeActivitySharedAction.OpenSpacePreview(it.id))
|
||||
is SpaceListViewEvents.OpenSpace -> sharedActionViewModel.post(HomeActivitySharedAction.OpenGroup)
|
||||
is SpaceListViewEvents.AddSpace -> sharedActionViewModel.post(HomeActivitySharedAction.AddSpace)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
@ -78,4 +79,8 @@ class SpaceListFragment @Inject constructor(
|
|||
override fun onSpaceSelected(spaceSummary: SpaceSummary) {
|
||||
viewModel.handle(SpaceListAction.SelectSpace(spaceSummary))
|
||||
}
|
||||
|
||||
override fun onAddSpaceSelected() {
|
||||
viewModel.handle(SpaceListAction.AddSpace)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,10 @@ package im.vector.app.features.spaces
|
|||
import com.airbnb.epoxy.EpoxyController
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.core.ui.list.genericButtonItem
|
||||
import im.vector.app.core.ui.list.genericFooterItem
|
||||
import im.vector.app.core.ui.list.genericItemHeader
|
||||
import im.vector.app.core.utils.DebouncedClickListener
|
||||
import im.vector.app.features.grouplist.homeSpaceSummaryItem
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
|
@ -103,9 +105,19 @@ class SpaceSummaryController @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Temporary item to create a new Space (will move with final design)
|
||||
|
||||
genericButtonItem {
|
||||
id("create")
|
||||
text(stringProvider.getString(R.string.add_space))
|
||||
iconRes(R.drawable.ic_add_black)
|
||||
buttonClickAction(DebouncedClickListener({ callback?.onAddSpaceSelected() }))
|
||||
}
|
||||
}
|
||||
|
||||
interface Callback {
|
||||
fun onSpaceSelected(spaceSummary: SpaceSummary)
|
||||
fun onAddSpaceSelected()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ const val ALL_COMMUNITIES_GROUP_ID = "+ALL_COMMUNITIES_GROUP_ID"
|
|||
|
||||
sealed class SpaceListAction : VectorViewModelAction {
|
||||
data class SelectSpace(val spaceSummary: SpaceSummary) : SpaceListAction()
|
||||
object AddSpace : SpaceListAction()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,6 +55,7 @@ sealed class SpaceListAction : VectorViewModelAction {
|
|||
sealed class SpaceListViewEvents : VectorViewEvents {
|
||||
object OpenSpace : SpaceListViewEvents()
|
||||
data class OpenSpaceSummary(val id: String) : SpaceListViewEvents()
|
||||
object AddSpace : SpaceListViewEvents()
|
||||
}
|
||||
|
||||
data class SpaceListViewState(
|
||||
|
@ -110,6 +112,7 @@ class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: Sp
|
|||
override fun handle(action: SpaceListAction) {
|
||||
when (action) {
|
||||
is SpaceListAction.SelectSpace -> handleSelectSpace(action)
|
||||
else -> handleAddSpace()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,6 +139,10 @@ class SpacesListViewModel @AssistedInject constructor(@Assisted initialState: Sp
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleAddSpace() {
|
||||
_viewEvents.post(SpaceListViewEvents.AddSpace)
|
||||
}
|
||||
|
||||
private fun observeGroupSummaries() {
|
||||
val roomSummaryQueryParams = roomSummaryQueryParams() {
|
||||
memberships = listOf(Membership.JOIN, Membership.INVITE)
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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 im.vector.app.features.spaces.create
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.utils.DebouncedClickListener
|
||||
import im.vector.app.databinding.FragmentSpaceCreateChooseTypeBinding
|
||||
import javax.inject.Inject
|
||||
|
||||
class ChooseSpaceTypeFragment @Inject constructor(
|
||||
// private val viewModelFactory: CreateSpaceViewModel.Factory,
|
||||
) : VectorBaseFragment<FragmentSpaceCreateChooseTypeBinding>() {
|
||||
|
||||
private val sharedViewModel: CreateSpaceViewModel by activityViewModel()
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) =
|
||||
FragmentSpaceCreateChooseTypeBinding.inflate(layoutInflater, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
views.publicButton.setOnClickListener(DebouncedClickListener({
|
||||
sharedViewModel.handle(CreateSpaceAction.SetRoomType(SpaceType.Public))
|
||||
}))
|
||||
|
||||
views.privateButton.setOnClickListener(DebouncedClickListener({
|
||||
sharedViewModel.handle(CreateSpaceAction.SetRoomType(SpaceType.Private))
|
||||
}))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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 im.vector.app.features.spaces.create
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentSpaceCreateGenericEpoxyFormBinding
|
||||
import javax.inject.Inject
|
||||
|
||||
class CreateSpaceDefaultRoomsFragment @Inject constructor(
|
||||
private val epoxyController: SpaceDefaultRoomEpoxyController
|
||||
) : VectorBaseFragment<FragmentSpaceCreateGenericEpoxyFormBinding>(), SpaceDefaultRoomEpoxyController.Listener {
|
||||
|
||||
private val sharedViewModel: CreateSpaceViewModel by activityViewModel()
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) =
|
||||
FragmentSpaceCreateGenericEpoxyFormBinding.inflate(layoutInflater, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
views.recyclerView.configureWith(epoxyController)
|
||||
epoxyController.listener = this
|
||||
|
||||
sharedViewModel.subscribe(this) {
|
||||
epoxyController.setData(it)
|
||||
}
|
||||
|
||||
views.nextButton.debouncedClicks {
|
||||
sharedViewModel.handle(CreateSpaceAction.NextFromDetails)
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// Epoxy controller listener methods
|
||||
// -----------------------------
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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 im.vector.app.features.spaces.create
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentSpaceCreateGenericEpoxyFormBinding
|
||||
import javax.inject.Inject
|
||||
|
||||
class CreateSpaceDetailsFragment @Inject constructor(
|
||||
private val epoxyController: SpaceDetailEpoxyController
|
||||
) : VectorBaseFragment<FragmentSpaceCreateGenericEpoxyFormBinding>(), SpaceDetailEpoxyController.Listener {
|
||||
|
||||
private val sharedViewModel: CreateSpaceViewModel by activityViewModel()
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?) =
|
||||
FragmentSpaceCreateGenericEpoxyFormBinding.inflate(layoutInflater, container, false)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
views.recyclerView.configureWith(epoxyController)
|
||||
epoxyController.listener = this
|
||||
|
||||
sharedViewModel.subscribe(this) {
|
||||
epoxyController.setData(it)
|
||||
}
|
||||
|
||||
views.nextButton.debouncedClicks {
|
||||
sharedViewModel.handle(CreateSpaceAction.NextFromDetails)
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// Epoxy controller listener methods
|
||||
// -----------------------------
|
||||
|
||||
override fun onAvatarDelete() {
|
||||
}
|
||||
|
||||
override fun onAvatarChange() {
|
||||
}
|
||||
|
||||
override fun onNameChange(newName: String) {
|
||||
sharedViewModel.handle(CreateSpaceAction.NameChanged(newName))
|
||||
}
|
||||
|
||||
override fun onTopicChange(newTopic: String) {
|
||||
sharedViewModel.handle(CreateSpaceAction.TopicChanged(newTopic))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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 im.vector.app.features.spaces.create
|
||||
|
||||
import android.net.Uri
|
||||
import com.airbnb.mvrx.ActivityViewModelContext
|
||||
import com.airbnb.mvrx.FragmentViewModelContext
|
||||
import com.airbnb.mvrx.MvRxState
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
|
||||
data class CreateSpaceState(
|
||||
val name: String? = null,
|
||||
val avatarUri: Uri? = null,
|
||||
val topic: String = "",
|
||||
val step: Step = Step.ChooseType,
|
||||
val spaceType: SpaceType? = null,
|
||||
val nameInlineError : String? = null,
|
||||
val defaultRooms: List<String>? = null
|
||||
) : MvRxState {
|
||||
|
||||
enum class Step {
|
||||
ChooseType,
|
||||
SetDetails,
|
||||
AddRooms
|
||||
}
|
||||
}
|
||||
|
||||
enum class SpaceType {
|
||||
Public,
|
||||
Private
|
||||
}
|
||||
|
||||
sealed class CreateSpaceAction : VectorViewModelAction {
|
||||
data class SetRoomType(val type: SpaceType) : CreateSpaceAction()
|
||||
data class NameChanged(val name: String) : CreateSpaceAction()
|
||||
data class TopicChanged(val topic: String) : CreateSpaceAction()
|
||||
object OnBackPressed : CreateSpaceAction()
|
||||
object NextFromDetails : CreateSpaceAction()
|
||||
}
|
||||
|
||||
sealed class CreateSpaceEvents : VectorViewEvents {
|
||||
object NavigateToDetails : CreateSpaceEvents()
|
||||
object NavigateToChooseType : CreateSpaceEvents()
|
||||
object NavigateToAddRooms : CreateSpaceEvents()
|
||||
object Dismiss : CreateSpaceEvents()
|
||||
}
|
||||
|
||||
class CreateSpaceViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: CreateSpaceState,
|
||||
private val session: Session,
|
||||
private val stringProvider: StringProvider
|
||||
) : VectorViewModel<CreateSpaceState, CreateSpaceAction, CreateSpaceEvents>(initialState) {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(initialState: CreateSpaceState): CreateSpaceViewModel
|
||||
}
|
||||
|
||||
companion object : MvRxViewModelFactory<CreateSpaceViewModel, CreateSpaceState> {
|
||||
|
||||
override fun create(viewModelContext: ViewModelContext, state: CreateSpaceState): CreateSpaceViewModel? {
|
||||
val factory = when (viewModelContext) {
|
||||
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
|
||||
is ActivityViewModelContext -> viewModelContext.activity as? Factory
|
||||
}
|
||||
return factory?.create(state) ?: error("You should let your activity/fragment implements Factory interface")
|
||||
}
|
||||
}
|
||||
|
||||
override fun handle(action: CreateSpaceAction) {
|
||||
when (action) {
|
||||
is CreateSpaceAction.SetRoomType -> {
|
||||
setState {
|
||||
copy(
|
||||
step = CreateSpaceState.Step.SetDetails,
|
||||
spaceType = action.type
|
||||
)
|
||||
}
|
||||
_viewEvents.post(CreateSpaceEvents.NavigateToDetails)
|
||||
}
|
||||
is CreateSpaceAction.NameChanged -> {
|
||||
setState {
|
||||
copy(
|
||||
nameInlineError = null,
|
||||
name = action.name
|
||||
)
|
||||
}
|
||||
}
|
||||
is CreateSpaceAction.TopicChanged -> {
|
||||
setState {
|
||||
copy(
|
||||
topic = action.topic
|
||||
)
|
||||
}
|
||||
}
|
||||
CreateSpaceAction.OnBackPressed -> {
|
||||
handleBackNavigation()
|
||||
}
|
||||
CreateSpaceAction.NextFromDetails -> {
|
||||
handleNextFromDetails()
|
||||
}
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleBackNavigation() = withState { state ->
|
||||
when (state.step) {
|
||||
CreateSpaceState.Step.ChooseType -> {
|
||||
_viewEvents.post(CreateSpaceEvents.Dismiss)
|
||||
}
|
||||
CreateSpaceState.Step.SetDetails -> {
|
||||
setState {
|
||||
copy(
|
||||
step = CreateSpaceState.Step.ChooseType
|
||||
)
|
||||
}
|
||||
_viewEvents.post(CreateSpaceEvents.NavigateToChooseType)
|
||||
}
|
||||
CreateSpaceState.Step.AddRooms -> {
|
||||
setState {
|
||||
copy(
|
||||
step = CreateSpaceState.Step.SetDetails
|
||||
)
|
||||
}
|
||||
_viewEvents.post(CreateSpaceEvents.NavigateToDetails)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleNextFromDetails() = withState { state ->
|
||||
if (state.name.isNullOrBlank()) {
|
||||
setState {
|
||||
copy(
|
||||
nameInlineError = stringProvider.getString(R.string.create_space_error_empty_field_space_name)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
setState {
|
||||
copy(
|
||||
step = CreateSpaceState.Step.AddRooms
|
||||
)
|
||||
}
|
||||
_viewEvents.post(CreateSpaceEvents.NavigateToAddRooms)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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 im.vector.app.features.spaces.create
|
||||
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.core.ui.list.GenericItem
|
||||
import im.vector.app.core.ui.list.genericFooterItem
|
||||
import im.vector.app.features.form.formEditTextItem
|
||||
import javax.inject.Inject
|
||||
|
||||
class SpaceDefaultRoomEpoxyController @Inject constructor(
|
||||
private val stringProvider: StringProvider,
|
||||
private val colorProvider: ColorProvider
|
||||
// private val avatarRenderer: AvatarRenderer
|
||||
) : TypedEpoxyController<CreateSpaceState>() {
|
||||
|
||||
var listener: Listener? = null
|
||||
|
||||
override fun buildModels(data: CreateSpaceState?) {
|
||||
genericFooterItem {
|
||||
id("info_help_header")
|
||||
style(GenericItem.STYLE.BIG_TEXT)
|
||||
text(stringProvider.getString(R.string.create_spaces_room_public_header))
|
||||
textColor(colorProvider.getColorFromAttribute(R.attr.riot_primary_text_color))
|
||||
}
|
||||
|
||||
genericFooterItem {
|
||||
id("info_help")
|
||||
text(stringProvider.getString(R.string.create_spaces_room_public_header_desc))
|
||||
textColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_secondary))
|
||||
}
|
||||
|
||||
formEditTextItem {
|
||||
id("roomName1")
|
||||
enabled(true)
|
||||
value(data?.name)
|
||||
hint(stringProvider.getString(R.string.create_room_name_hint))
|
||||
showBottomSeparator(false)
|
||||
// errorMessage(data?.nameInlineError)
|
||||
onTextChange { text ->
|
||||
// listener?.onNameChange(text)
|
||||
}
|
||||
}
|
||||
|
||||
formEditTextItem {
|
||||
id("roomName2")
|
||||
enabled(true)
|
||||
// value(data?.name)
|
||||
hint(stringProvider.getString(R.string.create_room_name_hint))
|
||||
showBottomSeparator(false)
|
||||
// errorMessage(data?.nameInlineError)
|
||||
onTextChange { text ->
|
||||
// listener?.onNameChange(text)
|
||||
}
|
||||
}
|
||||
|
||||
formEditTextItem {
|
||||
id("roomName3")
|
||||
enabled(true)
|
||||
// value(data?.name)
|
||||
hint(stringProvider.getString(R.string.create_room_name_hint))
|
||||
showBottomSeparator(false)
|
||||
// errorMessage(data?.nameInlineError)
|
||||
onTextChange { text ->
|
||||
// listener?.onNameChange(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
// fun onAvatarDelete()
|
||||
// fun onAvatarChange()
|
||||
// fun onNameChange(newName: String)
|
||||
// fun onTopicChange(newTopic: String)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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 im.vector.app.features.spaces.create
|
||||
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.core.ui.list.genericFooterItem
|
||||
import im.vector.app.features.form.formEditTextItem
|
||||
import im.vector.app.features.form.formEditableSquareAvatarItem
|
||||
import im.vector.app.features.form.formMultiLineEditTextItem
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import org.matrix.android.sdk.api.util.MatrixItem
|
||||
import javax.inject.Inject
|
||||
|
||||
class SpaceDetailEpoxyController @Inject constructor(
|
||||
private val stringProvider: StringProvider,
|
||||
private val avatarRenderer: AvatarRenderer
|
||||
) : TypedEpoxyController<CreateSpaceState>() {
|
||||
|
||||
var listener: Listener? = null
|
||||
|
||||
override fun buildModels(data: CreateSpaceState?) {
|
||||
genericFooterItem {
|
||||
id("info_help")
|
||||
text(
|
||||
if (data?.spaceType == SpaceType.Public) {
|
||||
stringProvider.getString(R.string.create_spaces_details_public_header)
|
||||
} else {
|
||||
stringProvider.getString(R.string.create_spaces_details_private_header)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
formEditableSquareAvatarItem {
|
||||
id("avatar")
|
||||
enabled(true)
|
||||
imageUri(data?.avatarUri)
|
||||
avatarRenderer(avatarRenderer)
|
||||
matrixItem(data?.name?.let { MatrixItem.RoomItem("", it, null).takeIf { !it.displayName.isNullOrBlank() } })
|
||||
clickListener { listener?.onAvatarChange() }
|
||||
deleteListener { listener?.onAvatarDelete() }
|
||||
}
|
||||
|
||||
formEditTextItem {
|
||||
id("name")
|
||||
enabled(true)
|
||||
value(data?.name)
|
||||
hint(stringProvider.getString(R.string.create_room_name_hint))
|
||||
showBottomSeparator(false)
|
||||
errorMessage(data?.nameInlineError)
|
||||
onTextChange { text ->
|
||||
listener?.onNameChange(text)
|
||||
}
|
||||
}
|
||||
|
||||
formMultiLineEditTextItem {
|
||||
id("topic")
|
||||
enabled(true)
|
||||
value(data?.topic)
|
||||
hint(stringProvider.getString(R.string.create_room_topic_hint))
|
||||
showBottomSeparator(false)
|
||||
textSizeSp(15)
|
||||
onTextChange { text ->
|
||||
listener?.onTopicChange(text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
fun onAvatarDelete()
|
||||
fun onAvatarChange()
|
||||
fun onNameChange(newName: String)
|
||||
fun onTopicChange(newTopic: String)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2021 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 im.vector.app.features.spaces.create
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.AttributeSet
|
||||
import android.util.TypedValue
|
||||
import androidx.appcompat.content.res.AppCompatResources.getDrawable
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.withStyledAttributes
|
||||
import im.vector.app.R
|
||||
import im.vector.app.databinding.ViewSpaceTypeButtonBinding
|
||||
|
||||
class WizardButtonView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int = 0)
|
||||
: ConstraintLayout(context, attrs, defStyle) {
|
||||
|
||||
private val views: ViewSpaceTypeButtonBinding
|
||||
|
||||
var title: String? = null
|
||||
set(value) {
|
||||
if (value != title) {
|
||||
field = value
|
||||
views.title.text = value
|
||||
}
|
||||
}
|
||||
|
||||
var subTitle: String? = null
|
||||
set(value) {
|
||||
if (value != subTitle) {
|
||||
field = value
|
||||
views.subTitle.text = value
|
||||
}
|
||||
}
|
||||
|
||||
var icon: Drawable? = null
|
||||
set(value) {
|
||||
if (value != icon) {
|
||||
field = value
|
||||
views.buttonImageView.setImageDrawable(value)
|
||||
}
|
||||
}
|
||||
|
||||
// private var tint: Int? = null
|
||||
// set(value) {
|
||||
// field = value
|
||||
// if (value != null) {
|
||||
// views.buttonImageView.imageTintList = ColorStateList.valueOf(value)
|
||||
// } else {
|
||||
// views.buttonImageView.clearColorFilter()
|
||||
// }
|
||||
// }
|
||||
|
||||
// var action: (() -> Unit)? = null
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.view_space_type_button, this)
|
||||
views = ViewSpaceTypeButtonBinding.bind(this)
|
||||
|
||||
if (isInEditMode) {
|
||||
title = "Title"
|
||||
subTitle = "This is doing something"
|
||||
}
|
||||
|
||||
context.withStyledAttributes(attrs, R.styleable.WizardButtonView) {
|
||||
title = getString(R.styleable.WizardButtonView_title) ?: ""
|
||||
subTitle = getString(R.styleable.WizardButtonView_subTitle) ?: ""
|
||||
icon = getDrawable(R.styleable.WizardButtonView_icon)
|
||||
// tint = getColor(R.styleable.WizardButtonView_iconTint, ThemeUtils.getColor(context, R.attr.riotx_text_primary))
|
||||
}
|
||||
|
||||
val outValue = TypedValue()
|
||||
context.theme.resolveAttribute(android.R.attr.selectableItemBackground, outValue, true)
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
this.foreground = getDrawable(context, outValue.resourceId)
|
||||
}
|
||||
|
||||
// views.content.isClickable = true
|
||||
// views.content.isFocusable = true
|
||||
// views.content.setOnClickListener {
|
||||
// action?.invoke()
|
||||
// }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="16dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="16">
|
||||
<path
|
||||
android:pathData="M6.4931,1.6667C5.569,1.6667 4.7811,2.2962 4.5568,3.165C4.5039,3.3699 4.4261,3.5713 4.2866,3.7303L4.0563,3.9928C3.8664,4.2092 3.5925,4.3333 3.3046,4.3333H1.3333C0.597,4.3333 0,4.9303 0,5.6667V13C0,13.7364 0.597,14.3333 1.3333,14.3333H14.6667C15.403,14.3333 16,13.7364 16,13V5.6667C16,4.9303 15.403,4.3333 14.6667,4.3333H12.6954C12.4075,4.3333 12.1336,4.2092 11.9437,3.9928L11.7134,3.7303C11.5739,3.5713 11.4961,3.3699 11.4432,3.165C11.219,2.2962 10.431,1.6667 9.5069,1.6667H6.4931ZM10.6667,9C10.6667,10.4727 9.4728,11.6667 8,11.6667C6.5272,11.6667 5.3333,10.4727 5.3333,9C5.3333,7.5272 6.5272,6.3333 8,6.3333C9.4728,6.3333 10.6667,7.5272 10.6667,9Z"
|
||||
android:fillColor="#737D8C"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
|
@ -0,0 +1,13 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M24,12C24,18.6274 18.6274,24 12,24C5.3726,24 0,18.6274 0,12C0,5.3726 5.3726,0 12,0C18.6274,0 24,5.3726 24,12Z"
|
||||
android:fillColor="#C1C6CD"/>
|
||||
<path
|
||||
android:pathData="M18.6999,18.8177L19.6243,15.9652C19.6324,15.9404 19.6365,15.9143 19.6365,15.8882V15.0473C19.6365,14.9823 19.6111,14.9197 19.5657,14.8731L18.7105,13.9934C18.6916,13.9739 18.6697,13.9577 18.6456,13.9453L16.8092,13.0009C16.7852,12.9885 16.7632,12.9723 16.7443,12.9529L15.8919,12.0761C15.8449,12.0277 15.7802,12.0004 15.7127,12.0004H12.2501C12.1121,12.0004 12.0001,11.8885 12.0001,11.7504V10.2868C12.0001,10.1487 11.8882,10.0368 11.7501,10.0368H9.3865C9.2484,10.0368 9.1365,9.9248 9.1365,9.7868V8.3798C9.1365,8.2215 9.2818,8.103 9.4369,8.1349L13.6089,8.9931C13.7639,9.0251 13.9092,8.9066 13.9092,8.7483V7.1928C13.9092,7.1277 13.9346,7.0652 13.98,7.0185L16.6034,4.3201C16.6978,4.2231 16.6978,4.0686 16.6034,3.9716L14.9023,2.2219C14.8769,2.1957 14.8461,2.1755 14.8121,2.1625L13.3697,1.613C12.4823,1.275 11.5072,1.2439 10.6001,1.5247L9.1365,1.9777C7.1638,2.6207 5.6129,4.1612 4.9568,6.1296L4.621,7.1369C4.5407,7.3779 4.4931,7.6285 4.4795,7.8822L4.3696,9.9275C4.3659,9.9972 4.3914,10.0652 4.44,10.1152L6.1992,11.9247C6.2463,11.9731 6.311,12.0004 6.3785,12.0004H8.1214C8.1612,12.0004 8.2004,12.0099 8.2358,12.0281L9.9554,12.9124C10.0387,12.9553 10.091,13.0411 10.091,13.1348V15.8701C10.091,15.908 10.0996,15.9454 10.1162,15.9794L10.9772,17.7506C11.019,17.8367 11.1063,17.8913 11.202,17.8913H12.8491C12.9166,17.8913 12.9812,17.9186 13.0283,17.967L13.9092,18.8731L14.8357,19.8261C14.8543,19.8452 14.8697,19.8671 14.8813,19.8911L15.6626,21.4982C15.7383,21.654 15.9458,21.6874 16.0667,21.5631L16.7729,20.8368L17.7274,19.8549L18.6413,18.9149C18.6681,18.8874 18.6881,18.8542 18.6999,18.8177Z"
|
||||
android:fillColor="#F4F6FA"
|
||||
android:fillAlpha="0.91"/>
|
||||
</vector>
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M11.3333,2C8.3878,2 6,4.3878 6,7.3333V10C4.8954,10 4,10.8954 4,12V20C4,21.1046 4.8954,22 6,22H18C19.1046,22 20,21.1046 20,20V12C20,10.8954 19.1046,10 18,10V7.3333C18,4.3878 15.6122,2 12.6667,2H11.3333ZM15.3333,10V7.3333C15.3333,5.8606 14.1394,4.6667 12.6667,4.6667H11.3333C9.8606,4.6667 8.6667,5.8606 8.6667,7.3333V10H15.3333Z"
|
||||
android:fillColor="#C1C6CD"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/headerText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="@string/create_spaces_type_header"
|
||||
android:textColor="?riotx_text_secondary"
|
||||
android:textSize="18sp"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="2dp"
|
||||
android:gravity="start"
|
||||
android:text="@string/create_spaces_choose_type_label"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@id/joinInfoHelpText"
|
||||
app:layout_constraintTop_toBottomOf="@id/headerText"
|
||||
app:layout_constraintVertical_bias="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/joinInfoHelpText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:gravity="start"
|
||||
android:text="@string/create_spaces_join_info_help"
|
||||
android:textColor="?riotx_text_secondary"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/publicButton" />
|
||||
|
||||
<im.vector.app.features.spaces.create.WizardButtonView
|
||||
android:id="@+id/publicButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:icon="@drawable/ic_public_room"
|
||||
app:layout_constraintBottom_toTopOf="@id/privateButton"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:subTitle="@string/space_type_public_desc"
|
||||
app:title="@string/space_type_public" />
|
||||
|
||||
<im.vector.app.features.spaces.create.WizardButtonView
|
||||
android:id="@+id/privateButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:icon="@drawable/ic_room_private"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:subTitle="@string/space_type_private_desc"
|
||||
app:title="@string/space_type_private" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</ScrollView>
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/buttonBar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:listitem="@layout/item_form_text_input" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/buttonBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?riotx_background"
|
||||
android:elevation="2dp"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/nextButton"
|
||||
style="@style/VectorButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/next_pf" />
|
||||
|
||||
</FrameLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/memberProfileInfoContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?riotx_background"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- I cannot do what I want using layer-list, do it manually here-->
|
||||
<FrameLayout
|
||||
android:id="@+id/itemEditableAvatarImageContainer"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:background="@drawable/rounded_rect_shape_8"
|
||||
android:contentDescription="@string/a11y_change_avatar"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemEditableAvatarImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:importantForAccessibility="no"
|
||||
android:scaleType="fitCenter"
|
||||
tools:alpha="0.3"
|
||||
tools:src="@tools:sample/avatars" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemEditableAvatarDelete"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:background="@drawable/header_panel_round_background"
|
||||
android:contentDescription="@string/a11y_delete_avatar"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_delete"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintCircle="@+id/itemEditableAvatarImageContainer"
|
||||
app:layout_constraintCircleAngle="45"
|
||||
app:layout_constraintCircleRadius="48dp"
|
||||
app:tint="@color/riotx_destructive_accent"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
||||
<ImageView
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_gravity="center"
|
||||
android:background="@drawable/circle"
|
||||
android:backgroundTint="?riotx_background"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_camera_plain"
|
||||
app:tint="?riotx_text_secondary"
|
||||
app:layout_constraintCircle="@+id/itemEditableAvatarImageContainer"
|
||||
app:layout_constraintCircleAngle="135"
|
||||
app:layout_constraintCircleRadius="48dp"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/rounded_rect_shape_8"
|
||||
android:id="@+id/content"
|
||||
android:padding="4dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/buttonImageView"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_margin="8dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:src="@drawable/ic_public_room"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:gravity="start"
|
||||
android:textColor="?riotx_text_primary"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toStartOf="@id/rightChevron"
|
||||
app:layout_constraintStart_toEndOf="@id/buttonImageView"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Public" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/subTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:gravity="start"
|
||||
android:textColor="?riotx_text_secondary"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="normal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/rightChevron"
|
||||
app:layout_constraintStart_toEndOf="@id/buttonImageView"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_goneMarginBottom="8dp"
|
||||
tools:text="Open to anyone, best for communities" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/rightChevron"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:src="@drawable/ic_material_chevron_right_black"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="?riotx_text_secondary" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -54,8 +54,10 @@
|
|||
<attr name="forceStartPadding" format="boolean" />
|
||||
</declare-styleable>
|
||||
|
||||
<attr name="iconTint" format="color" />
|
||||
|
||||
<declare-styleable name="SignOutBottomSheetActionButton">
|
||||
<attr name="iconTint" format="color" />
|
||||
<attr name="iconTint"/>
|
||||
<attr name="actionTitle" />
|
||||
<attr name="leftIcon" />
|
||||
<attr name="textColor" format="color" />
|
||||
|
@ -68,4 +70,12 @@
|
|||
<enum name="continue_with" value="2" />
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="WizardButtonView">
|
||||
<attr name="icon" format="reference" />
|
||||
<attr name="iconTint"/>
|
||||
<attr name="title" format="string" />
|
||||
<attr name="subTitle" format="string" />
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -3259,4 +3259,22 @@
|
|||
<string name="event_status_failed_messages_warning">Messages failed to send</string>
|
||||
<string name="event_status_delete_all_failed_dialog_title">Delete unsent messages</string>
|
||||
<string name="event_status_delete_all_failed_dialog_message">Are you sure you want to delete all unsent messages in this room?</string>
|
||||
|
||||
<string name="add_space">Add Space</string>
|
||||
<string name="your_public_space">Your public space</string>
|
||||
<string name="create_spaces_type_header">Spaces are a new way to group rooms and people</string>
|
||||
<string name="create_spaces_choose_type_label">What type of space do you want to create?</string>
|
||||
<string name="create_spaces_join_info_help">To join an existing space, you need an invite.</string>
|
||||
<string name="space_type_public">Public</string>
|
||||
<string name="space_type_public_desc">Open to anyone, best for communities</string>
|
||||
<string name="space_type_private">Private</string>
|
||||
<string name="space_type_private_desc">Invite only, best for yourself or teams</string>
|
||||
<string name="activity_create_space_title">Create a space</string>
|
||||
<string name="create_spaces_details_public_header">Add some details to help it stand out. You can change these at any point.</string>
|
||||
<string name="create_spaces_details_private_header">Add some details to help people identify it. You can change these at any point.</string>
|
||||
<string name="create_space_error_empty_field_space_name">Give it a name to continue.</string>
|
||||
<string name="create_spaces_room_public_header">What are some discussions you want to have in Runner’s World?</string>
|
||||
<string name="create_spaces_room_public_header_desc">We’ll create rooms for them, and auto-join everyone. You can add more later too.</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue