Add custom server
This commit is contained in:
parent
f30eb4af8a
commit
cbed1afaaa
|
@ -0,0 +1 @@
|
|||
Allow user to add custom "network" in room search
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright 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.core.ui.list
|
||||
|
||||
import android.view.View
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
|
||||
/**
|
||||
* A generic item with empty space.
|
||||
*/
|
||||
@EpoxyModelClass(layout = R.layout.item_generic_space)
|
||||
abstract class GenericSpaceItem : VectorEpoxyModel<GenericSpaceItem.Holder>() {
|
||||
|
||||
@EpoxyAttribute
|
||||
var heightInPx: Int = 0
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
holder.space.updateLayoutParams {
|
||||
height = heightInPx
|
||||
}
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val space by bind<View>(R.id.item_generic_space)
|
||||
}
|
||||
}
|
|
@ -33,6 +33,9 @@ abstract class SettingsContinueCancelItem : EpoxyModelWithHolder<SettingsContinu
|
|||
@EpoxyAttribute
|
||||
var continueOnClick: ClickListener? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var canContinue: Boolean = true
|
||||
|
||||
@EpoxyAttribute
|
||||
var cancelOnClick: ClickListener? = null
|
||||
|
||||
|
@ -43,6 +46,7 @@ abstract class SettingsContinueCancelItem : EpoxyModelWithHolder<SettingsContinu
|
|||
|
||||
continueText?.let { holder.continueButton.text = it }
|
||||
holder.continueButton.onClick(continueOnClick)
|
||||
holder.continueButton.isEnabled = canContinue
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
|
|
|
@ -51,6 +51,7 @@ abstract class FormEditTextItem : VectorEpoxyModel<FormEditTextItem.Holder>() {
|
|||
@EpoxyAttribute
|
||||
var inputType: Int? = null
|
||||
|
||||
// TODO Should be true by default
|
||||
@EpoxyAttribute
|
||||
var singleLine: Boolean? = null
|
||||
|
||||
|
|
|
@ -24,6 +24,11 @@ data class RoomDirectoryServer(
|
|||
*/
|
||||
val isUserServer: Boolean,
|
||||
|
||||
/**
|
||||
* True if manually added, so it can be removed by the user
|
||||
*/
|
||||
val isManuallyAdded: Boolean,
|
||||
|
||||
/**
|
||||
* Supported protocols
|
||||
* TODO Rename RoomDirectoryData to RoomDirectoryProtocols
|
||||
|
|
|
@ -29,7 +29,8 @@ class RoomDirectoryListCreator @Inject constructor(
|
|||
private val session: Session
|
||||
) {
|
||||
|
||||
fun computeDirectories(thirdPartyProtocolData: Map<String, ThirdPartyProtocol>): List<RoomDirectoryServer> {
|
||||
fun computeDirectories(thirdPartyProtocolData: Map<String, ThirdPartyProtocol>,
|
||||
customHomeservers: Set<String>): List<RoomDirectoryServer> {
|
||||
val result = ArrayList<RoomDirectoryServer>()
|
||||
|
||||
val protocols = ArrayList<RoomDirectoryData>()
|
||||
|
@ -75,6 +76,7 @@ class RoomDirectoryListCreator @Inject constructor(
|
|||
RoomDirectoryServer(
|
||||
serverName = userHsName,
|
||||
isUserServer = true,
|
||||
isManuallyAdded = false,
|
||||
protocols = protocols
|
||||
)
|
||||
)
|
||||
|
@ -88,6 +90,7 @@ class RoomDirectoryListCreator @Inject constructor(
|
|||
RoomDirectoryServer(
|
||||
serverName = it,
|
||||
isUserServer = false,
|
||||
isManuallyAdded = false,
|
||||
protocols = listOf(
|
||||
RoomDirectoryData(
|
||||
homeServer = it,
|
||||
|
@ -99,7 +102,25 @@ class RoomDirectoryListCreator @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
// TODO Add manually added server by the user
|
||||
// Add manually added server by the user
|
||||
customHomeservers
|
||||
.forEach {
|
||||
// Use the server name as a default display name
|
||||
result.add(
|
||||
RoomDirectoryServer(
|
||||
serverName = it,
|
||||
isUserServer = false,
|
||||
isManuallyAdded = true,
|
||||
protocols = listOf(
|
||||
RoomDirectoryData(
|
||||
homeServer = it,
|
||||
displayName = RoomDirectoryData.MATRIX_PROTOCOL_NAME,
|
||||
includeAllNetworks = false
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -17,7 +17,14 @@
|
|||
package im.vector.app.features.roomdirectory.picker
|
||||
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
import im.vector.app.features.roomdirectory.RoomDirectoryServer
|
||||
|
||||
sealed class RoomDirectoryPickerAction : VectorViewModelAction {
|
||||
object Retry : RoomDirectoryPickerAction()
|
||||
object EnterEditMode : RoomDirectoryPickerAction()
|
||||
object ExitEditMode : RoomDirectoryPickerAction()
|
||||
data class SetServerUrl(val url: String) : RoomDirectoryPickerAction()
|
||||
data class RemoveServer(val roomDirectoryServer: RoomDirectoryServer) : RoomDirectoryPickerAction()
|
||||
|
||||
object Submit : RoomDirectoryPickerAction()
|
||||
}
|
||||
|
|
|
@ -16,10 +16,14 @@
|
|||
|
||||
package im.vector.app.features.roomdirectory.picker
|
||||
|
||||
import android.text.InputType
|
||||
import android.view.View
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Incomplete
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.dividerItem
|
||||
import im.vector.app.core.epoxy.errorWithRetryItem
|
||||
|
@ -28,13 +32,22 @@ import im.vector.app.core.error.ErrorFormatter
|
|||
import im.vector.app.core.extensions.join
|
||||
import im.vector.app.core.resources.ColorProvider
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.core.ui.list.genericButtonItem
|
||||
import im.vector.app.core.ui.list.genericSpaceItem
|
||||
import im.vector.app.core.utils.DimensionConverter
|
||||
import im.vector.app.features.discovery.settingsContinueCancelItem
|
||||
import im.vector.app.features.discovery.settingsInformationItem
|
||||
import im.vector.app.features.form.formEditTextItem
|
||||
import im.vector.app.features.roomdirectory.RoomDirectoryData
|
||||
import im.vector.app.features.roomdirectory.RoomDirectoryServer
|
||||
import org.matrix.android.sdk.api.failure.Failure
|
||||
import javax.inject.Inject
|
||||
import javax.net.ssl.HttpsURLConnection
|
||||
|
||||
class RoomDirectoryPickerController @Inject constructor(
|
||||
private val stringProvider: StringProvider,
|
||||
colorProvider: ColorProvider,
|
||||
private val colorProvider: ColorProvider,
|
||||
private val dimensionConverter: DimensionConverter,
|
||||
private val errorFormatter: ErrorFormatter,
|
||||
private val roomDirectoryListCreator: RoomDirectoryListCreator
|
||||
) : TypedEpoxyController<RoomDirectoryPickerViewState>() {
|
||||
|
@ -44,16 +57,24 @@ class RoomDirectoryPickerController @Inject constructor(
|
|||
|
||||
private val dividerColor = colorProvider.getColorFromAttribute(R.attr.vctr_list_divider_color)
|
||||
|
||||
override fun buildModels(viewState: RoomDirectoryPickerViewState) {
|
||||
override fun buildModels(data: RoomDirectoryPickerViewState) {
|
||||
val host = this
|
||||
|
||||
when (val asyncThirdPartyProtocol = viewState.asyncThirdPartyRequest) {
|
||||
when (val asyncThirdPartyProtocol = data.asyncThirdPartyRequest) {
|
||||
is Success -> {
|
||||
val directories = roomDirectoryListCreator.computeDirectories(asyncThirdPartyProtocol())
|
||||
val directories = roomDirectoryListCreator.computeDirectories(
|
||||
asyncThirdPartyProtocol(),
|
||||
data.customHomeservers
|
||||
)
|
||||
directories.join(
|
||||
each = { _, roomDirectoryServer -> buildDirectory(roomDirectoryServer) },
|
||||
between = { idx, _ -> buildDivider(idx) }
|
||||
)
|
||||
buildForm(data)
|
||||
genericSpaceItem {
|
||||
id("space_bottom")
|
||||
heightInPx(host.dimensionConverter.dpToPx(16))
|
||||
}
|
||||
}
|
||||
is Incomplete -> {
|
||||
loadingItem {
|
||||
|
@ -70,6 +91,77 @@ class RoomDirectoryPickerController @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun buildForm(data: RoomDirectoryPickerViewState) {
|
||||
buildDivider(1000)
|
||||
val host = this
|
||||
if (data.inEditMode) {
|
||||
genericSpaceItem {
|
||||
id("form_space")
|
||||
heightInPx(host.dimensionConverter.dpToPx(16))
|
||||
}
|
||||
settingsInformationItem {
|
||||
id("form_notice")
|
||||
message(host.stringProvider.getString(R.string.directory_add_a_new_server_prompt))
|
||||
colorProvider(host.colorProvider)
|
||||
}
|
||||
genericSpaceItem {
|
||||
id("form_space_2")
|
||||
heightInPx(host.dimensionConverter.dpToPx(8))
|
||||
}
|
||||
formEditTextItem {
|
||||
id("edit")
|
||||
showBottomSeparator(false)
|
||||
value(data.enteredServer)
|
||||
hint(host.stringProvider.getString(R.string.directory_server_placeholder))
|
||||
inputType(InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_URI)
|
||||
onTextChange { text ->
|
||||
host.callback?.onEnterServerChange(text)
|
||||
}
|
||||
when (data.addServerAsync) {
|
||||
Uninitialized -> enabled(true)
|
||||
is Loading -> enabled(false)
|
||||
is Success -> enabled(false)
|
||||
is Fail -> {
|
||||
enabled(true)
|
||||
errorMessage(host.getErrorMessage(data.addServerAsync.error))
|
||||
}
|
||||
}
|
||||
}
|
||||
when (data.addServerAsync) {
|
||||
Uninitialized,
|
||||
is Fail -> settingsContinueCancelItem {
|
||||
id("continueCancel")
|
||||
continueText(host.stringProvider.getString(R.string.ok))
|
||||
canContinue(data.enteredServer.isNotEmpty())
|
||||
continueOnClick { host.callback?.onSubmitServer() }
|
||||
cancelOnClick { host.callback?.onCancelEnterServer() }
|
||||
}
|
||||
is Loading -> loadingItem {
|
||||
id("addLoading")
|
||||
}
|
||||
is Success -> Unit /* This is a transitive state */
|
||||
}
|
||||
} else {
|
||||
genericButtonItem {
|
||||
id("add")
|
||||
text(host.stringProvider.getString(R.string.directory_add_a_new_server))
|
||||
textColor(host.colorProvider.getColor(R.color.riotx_accent))
|
||||
buttonClickAction(View.OnClickListener {
|
||||
host.callback?.onStartEnterServer()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getErrorMessage(error: Throwable): String {
|
||||
return if (error is Failure.ServerError
|
||||
&& error.httpCode == HttpsURLConnection.HTTP_INTERNAL_ERROR /* 500 */) {
|
||||
stringProvider.getString(R.string.directory_add_a_new_server_error)
|
||||
} else {
|
||||
errorFormatter.toHumanReadable(error)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildDivider(idx: Int) {
|
||||
val host = this
|
||||
dividerItem {
|
||||
|
@ -81,8 +173,10 @@ class RoomDirectoryPickerController @Inject constructor(
|
|||
private fun buildDirectory(roomDirectoryServer: RoomDirectoryServer) {
|
||||
val host = this
|
||||
roomDirectoryServerItem {
|
||||
id("server_" + roomDirectoryServer.serverName)
|
||||
id("server_$roomDirectoryServer")
|
||||
serverName(roomDirectoryServer.serverName)
|
||||
canRemove(roomDirectoryServer.isManuallyAdded)
|
||||
removeListener { host.callback?.onRemoveServer(roomDirectoryServer) }
|
||||
|
||||
if (roomDirectoryServer.isUserServer) {
|
||||
serverDescription(host.stringProvider.getString(R.string.directory_your_server))
|
||||
|
@ -91,7 +185,7 @@ class RoomDirectoryPickerController @Inject constructor(
|
|||
|
||||
roomDirectoryServer.protocols.forEach { roomDirectoryData ->
|
||||
roomDirectoryItem {
|
||||
id("server_" + roomDirectoryServer.serverName + "_proto_" + roomDirectoryData.displayName)
|
||||
id("server_${roomDirectoryServer}_proto_$roomDirectoryData")
|
||||
directoryName(
|
||||
if (roomDirectoryData.includeAllNetworks) {
|
||||
host.stringProvider.getString(R.string.directory_server_all_rooms_on_server, roomDirectoryServer.serverName)
|
||||
|
@ -117,5 +211,10 @@ class RoomDirectoryPickerController @Inject constructor(
|
|||
interface Callback {
|
||||
fun onRoomDirectoryClicked(roomDirectoryData: RoomDirectoryData)
|
||||
fun retry()
|
||||
fun onStartEnterServer()
|
||||
fun onEnterServerChange(server: String)
|
||||
fun onSubmitServer()
|
||||
fun onCancelEnterServer()
|
||||
fun onRemoveServer(roomDirectoryServer: RoomDirectoryServer)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,20 +28,22 @@ import com.airbnb.mvrx.withState
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.platform.OnBackPressed
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentRoomDirectoryPickerBinding
|
||||
import im.vector.app.features.roomdirectory.RoomDirectoryAction
|
||||
import im.vector.app.features.roomdirectory.RoomDirectoryData
|
||||
import im.vector.app.features.roomdirectory.RoomDirectoryServer
|
||||
import im.vector.app.features.roomdirectory.RoomDirectorySharedAction
|
||||
import im.vector.app.features.roomdirectory.RoomDirectorySharedActionViewModel
|
||||
import im.vector.app.features.roomdirectory.RoomDirectoryViewModel
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
// TODO Menu to add custom room directory (not done in RiotWeb so far...)
|
||||
class RoomDirectoryPickerFragment @Inject constructor(val roomDirectoryPickerViewModelFactory: RoomDirectoryPickerViewModel.Factory,
|
||||
private val roomDirectoryPickerController: RoomDirectoryPickerController
|
||||
) : VectorBaseFragment<FragmentRoomDirectoryPickerBinding>(),
|
||||
OnBackPressed,
|
||||
RoomDirectoryPickerController.Callback {
|
||||
|
||||
private val viewModel: RoomDirectoryViewModel by activityViewModel()
|
||||
|
@ -77,18 +79,6 @@ class RoomDirectoryPickerFragment @Inject constructor(val roomDirectoryPickerVie
|
|||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun getMenuRes() = R.menu.menu_directory_server_picker
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
if (item.itemId == R.id.action_add_custom_hs) {
|
||||
// TODO
|
||||
vectorBaseActivity.notImplemented("Entering custom homeserver")
|
||||
return true
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun setupRecyclerView() {
|
||||
views.roomDirectoryPickerList.configureWith(roomDirectoryPickerController)
|
||||
roomDirectoryPickerController.callback = this
|
||||
|
@ -101,6 +91,26 @@ class RoomDirectoryPickerFragment @Inject constructor(val roomDirectoryPickerVie
|
|||
sharedActionViewModel.post(RoomDirectorySharedAction.Back)
|
||||
}
|
||||
|
||||
override fun onStartEnterServer() {
|
||||
pickerViewModel.handle(RoomDirectoryPickerAction.EnterEditMode)
|
||||
}
|
||||
|
||||
override fun onCancelEnterServer() {
|
||||
pickerViewModel.handle(RoomDirectoryPickerAction.ExitEditMode)
|
||||
}
|
||||
|
||||
override fun onEnterServerChange(server: String) {
|
||||
pickerViewModel.handle(RoomDirectoryPickerAction.SetServerUrl(server))
|
||||
}
|
||||
|
||||
override fun onSubmitServer() {
|
||||
pickerViewModel.handle(RoomDirectoryPickerAction.Submit)
|
||||
}
|
||||
|
||||
override fun onRemoveServer(roomDirectoryServer: RoomDirectoryServer) {
|
||||
pickerViewModel.handle(RoomDirectoryPickerAction.RemoveServer(roomDirectoryServer))
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
(activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.select_room_directory)
|
||||
|
@ -115,4 +125,16 @@ class RoomDirectoryPickerFragment @Inject constructor(val roomDirectoryPickerVie
|
|||
// Populate list with Epoxy
|
||||
roomDirectoryPickerController.setData(state)
|
||||
}
|
||||
|
||||
override fun onBackPressed(toolbarButton: Boolean): Boolean {
|
||||
// Leave the add server mode if started
|
||||
return withState(pickerViewModel) {
|
||||
if (it.inEditMode) {
|
||||
pickerViewModel.handle(RoomDirectoryPickerAction.ExitEditMode)
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,18 +22,24 @@ import com.airbnb.mvrx.FragmentViewModelContext
|
|||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.MvRxViewModelFactory
|
||||
import com.airbnb.mvrx.Success
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import com.airbnb.mvrx.ViewModelContext
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedInject
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.EmptyViewEvents
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.ui.UiStateRepository
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
|
||||
|
||||
class RoomDirectoryPickerViewModel @AssistedInject constructor(@Assisted initialState: RoomDirectoryPickerViewState,
|
||||
private val session: Session)
|
||||
: VectorViewModel<RoomDirectoryPickerViewState, RoomDirectoryPickerAction, EmptyViewEvents>(initialState) {
|
||||
class RoomDirectoryPickerViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: RoomDirectoryPickerViewState,
|
||||
private val session: Session,
|
||||
private val uiStateRepository: UiStateRepository
|
||||
) : VectorViewModel<RoomDirectoryPickerViewState, RoomDirectoryPickerAction, EmptyViewEvents>(initialState) {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
|
@ -51,6 +57,7 @@ class RoomDirectoryPickerViewModel @AssistedInject constructor(@Assisted initial
|
|||
|
||||
init {
|
||||
load()
|
||||
loadCustomRoomDirectoryHomeservers()
|
||||
}
|
||||
|
||||
private fun load() {
|
||||
|
@ -71,9 +78,89 @@ class RoomDirectoryPickerViewModel @AssistedInject constructor(@Assisted initial
|
|||
}
|
||||
}
|
||||
|
||||
private fun loadCustomRoomDirectoryHomeservers() {
|
||||
setState {
|
||||
copy(
|
||||
customHomeservers = uiStateRepository.getCustomRoomDirectoryHomeservers(session.sessionId)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun handle(action: RoomDirectoryPickerAction) {
|
||||
when (action) {
|
||||
RoomDirectoryPickerAction.Retry -> load()
|
||||
RoomDirectoryPickerAction.Retry -> load()
|
||||
RoomDirectoryPickerAction.EnterEditMode -> handleEnterEditMode()
|
||||
RoomDirectoryPickerAction.ExitEditMode -> handleExitEditMode()
|
||||
is RoomDirectoryPickerAction.SetServerUrl -> handleSetServerUrl(action)
|
||||
RoomDirectoryPickerAction.Submit -> handleSubmit()
|
||||
is RoomDirectoryPickerAction.RemoveServer -> handleRemoveServer(action)
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun handleEnterEditMode() {
|
||||
setState {
|
||||
copy(
|
||||
inEditMode = true,
|
||||
enteredServer = "",
|
||||
addServerAsync = Uninitialized
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleExitEditMode() {
|
||||
setState {
|
||||
copy(
|
||||
inEditMode = false,
|
||||
enteredServer = "",
|
||||
addServerAsync = Uninitialized
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSetServerUrl(action: RoomDirectoryPickerAction.SetServerUrl) {
|
||||
setState {
|
||||
copy(
|
||||
enteredServer = action.url,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSubmit() = withState { state ->
|
||||
viewModelScope.launch {
|
||||
setState {
|
||||
copy(addServerAsync = Loading())
|
||||
}
|
||||
try {
|
||||
session.getPublicRooms(
|
||||
server = state.enteredServer,
|
||||
publicRoomsParams = PublicRoomsParams(limit = 1)
|
||||
)
|
||||
// Success, let add the server to our local repository, and update the state
|
||||
val newSet = uiStateRepository.getCustomRoomDirectoryHomeservers(session.sessionId) + state.enteredServer
|
||||
uiStateRepository.setCustomRoomDirectoryHomeservers(session.sessionId, newSet)
|
||||
setState {
|
||||
copy(
|
||||
inEditMode = false,
|
||||
enteredServer = "",
|
||||
addServerAsync = Uninitialized,
|
||||
customHomeservers = newSet
|
||||
)
|
||||
}
|
||||
} catch (failure: Throwable) {
|
||||
setState {
|
||||
copy(addServerAsync = Fail(failure))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRemoveServer(action: RoomDirectoryPickerAction.RemoveServer) {
|
||||
val newSet = uiStateRepository.getCustomRoomDirectoryHomeservers(session.sessionId) - action.roomDirectoryServer.serverName
|
||||
uiStateRepository.setCustomRoomDirectoryHomeservers(session.sessionId, newSet)
|
||||
setState {
|
||||
copy(
|
||||
customHomeservers = newSet
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,5 +22,9 @@ import com.airbnb.mvrx.Uninitialized
|
|||
import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol
|
||||
|
||||
data class RoomDirectoryPickerViewState(
|
||||
val asyncThirdPartyRequest: Async<Map<String, ThirdPartyProtocol>> = Uninitialized
|
||||
val asyncThirdPartyRequest: Async<Map<String, ThirdPartyProtocol>> = Uninitialized,
|
||||
val customHomeservers: Set<String> = emptySet(),
|
||||
val inEditMode: Boolean = false,
|
||||
val enteredServer: String = "",
|
||||
val addServerAsync: Async<Unit> = Uninitialized
|
||||
) : MvRxState
|
||||
|
|
|
@ -16,12 +16,16 @@
|
|||
|
||||
package im.vector.app.features.roomdirectory.picker
|
||||
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
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.VectorEpoxyModel
|
||||
import im.vector.app.core.epoxy.onClick
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
|
||||
@EpoxyModelClass(layout = R.layout.item_room_directory_server)
|
||||
|
@ -33,14 +37,23 @@ abstract class RoomDirectoryServerItem : VectorEpoxyModel<RoomDirectoryServerIte
|
|||
@EpoxyAttribute
|
||||
var serverDescription: String? = null
|
||||
|
||||
@EpoxyAttribute
|
||||
var canRemove: Boolean = false
|
||||
|
||||
@EpoxyAttribute
|
||||
var removeListener: ClickListener? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
holder.nameView.text = serverName
|
||||
holder.descriptionView.setTextOrHide(serverDescription)
|
||||
holder.deleteView.isVisible = canRemove
|
||||
holder.deleteView.onClick(removeListener)
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val nameView by bind<TextView>(R.id.itemRoomDirectoryServerName)
|
||||
val descriptionView by bind<TextView>(R.id.itemRoomDirectoryServerDescription)
|
||||
val deleteView by bind<View>(R.id.itemRoomDirectoryServerRemove)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ class SharedPreferencesUiStateRepository @Inject constructor(
|
|||
override fun getDisplayMode(): RoomListDisplayMode {
|
||||
return when (sharedPreferences.getInt(KEY_DISPLAY_MODE, VALUE_DISPLAY_MODE_CATCHUP)) {
|
||||
VALUE_DISPLAY_MODE_PEOPLE -> RoomListDisplayMode.PEOPLE
|
||||
VALUE_DISPLAY_MODE_ROOMS -> RoomListDisplayMode.ROOMS
|
||||
VALUE_DISPLAY_MODE_ROOMS -> RoomListDisplayMode.ROOMS
|
||||
else -> if (vectorPreferences.labAddNotificationTab()) {
|
||||
RoomListDisplayMode.NOTIFICATIONS
|
||||
} else {
|
||||
|
@ -89,6 +89,18 @@ class SharedPreferencesUiStateRepository @Inject constructor(
|
|||
return sharedPreferences.getBoolean("$KEY_SELECTED_METHOD@$sessionId", true)
|
||||
}
|
||||
|
||||
override fun setCustomRoomDirectoryHomeservers(sessionId: String, servers: Set<String>) {
|
||||
sharedPreferences.edit {
|
||||
putStringSet("$KEY_CUSTOM_DIRECTORY_HOMESERVER@$sessionId", servers)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCustomRoomDirectoryHomeservers(sessionId: String): Set<String> {
|
||||
return sharedPreferences.getStringSet("$KEY_CUSTOM_DIRECTORY_HOMESERVER@$sessionId", null)
|
||||
.orEmpty()
|
||||
.toSet()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KEY_DISPLAY_MODE = "UI_STATE_DISPLAY_MODE"
|
||||
private const val VALUE_DISPLAY_MODE_CATCHUP = 0
|
||||
|
@ -98,5 +110,7 @@ class SharedPreferencesUiStateRepository @Inject constructor(
|
|||
private const val KEY_SELECTED_SPACE = "UI_STATE_SELECTED_SPACE"
|
||||
private const val KEY_SELECTED_GROUP = "UI_STATE_SELECTED_GROUP"
|
||||
private const val KEY_SELECTED_METHOD = "UI_STATE_SELECTED_METHOD"
|
||||
|
||||
private const val KEY_CUSTOM_DIRECTORY_HOMESERVER = "KEY_CUSTOM_DIRECTORY_HOMESERVER"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ interface UiStateRepository {
|
|||
|
||||
fun storeDisplayMode(displayMode: RoomListDisplayMode)
|
||||
|
||||
// TODO Handle SharedPreference per session in a better way, also to cleanup when login out
|
||||
fun storeSelectedSpace(spaceId: String?, sessionId: String)
|
||||
fun storeSelectedGroup(groupId: String?, sessionId: String)
|
||||
|
||||
|
@ -40,4 +41,7 @@ interface UiStateRepository {
|
|||
fun getSelectedSpace(sessionId: String): String?
|
||||
fun getSelectedGroup(sessionId: String): String?
|
||||
fun isGroupingMethodSpace(sessionId: String): Boolean
|
||||
|
||||
fun setCustomRoomDirectoryHomeservers(sessionId: String, servers: Set<String>)
|
||||
fun getCustomRoomDirectoryHomeservers(sessionId: String): Set<String>
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Space xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/item_generic_space"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/layout_vertical_margin" />
|
|
@ -12,7 +12,7 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:maxLines="2"
|
||||
|
@ -20,10 +20,11 @@
|
|||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@+id/itemRoomDirectoryServerDescription"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/itemRoomDirectoryServerRemove"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_goneMarginEnd="@dimen/layout_horizontal_margin"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<TextView
|
||||
|
@ -31,7 +32,7 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:maxLines="2"
|
||||
|
@ -39,10 +40,28 @@
|
|||
android:textSize="15sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/itemRoomDirectoryServerRemove"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/itemRoomDirectoryServerName"
|
||||
app:layout_goneMarginEnd="@dimen/layout_horizontal_margin"
|
||||
tools:text="@string/directory_your_server"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/itemRoomDirectoryServerRemove"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
||||
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
||||
android:contentDescription="@string/avatar"
|
||||
android:padding="8dp"
|
||||
android:src="@drawable/ic_delete"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="@color/vector_error_color"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_add_custom_hs"
|
||||
android:icon="@drawable/ic_add_black"
|
||||
android:title="@string/action_open"
|
||||
android:visible="@bool/false_not_implemented"
|
||||
app:iconTint="?colorAccent"
|
||||
app:showAsAction="always" />
|
||||
|
||||
</menu>
|
|
@ -1584,10 +1584,13 @@
|
|||
<string name="select_room_directory">Select a room directory</string>
|
||||
<string name="directory_server_fail_to_retrieve_server">The server may be unavailable or overloaded</string>
|
||||
<string name="directory_server_type_homeserver">Type a homeserver to list public rooms from</string>
|
||||
<string name="directory_server_placeholder">Homeserver URL</string>
|
||||
<string name="directory_server_placeholder">Server name</string>
|
||||
<string name="directory_server_all_rooms_on_server">All rooms on %s server</string>
|
||||
<string name="directory_server_native_rooms">All native %s rooms</string>
|
||||
<string name="directory_your_server">Your server</string>
|
||||
<string name="directory_add_a_new_server">Add a new server</string>
|
||||
<string name="directory_add_a_new_server_prompt">Enter the name of a new server you want to explore.</string>
|
||||
<string name="directory_add_a_new_server_error">"Can't find this server or its room list"</string>
|
||||
|
||||
<!-- Lock screen-->
|
||||
<string name="lock_screen_hint">Type here…</string>
|
||||
|
|
Loading…
Reference in New Issue