Add a screen to view details about the homeserver

This commit is contained in:
Benoit Marty 2021-02-16 17:01:35 +01:00 committed by Benoit Marty
parent a8be5ed6b0
commit 531beb0a86
13 changed files with 410 additions and 2 deletions

View file

@ -24,6 +24,12 @@ import com.squareup.moshi.JsonClass
*/
@JsonClass(generateAdapter = true)
internal data class FederationGetVersionResult(
@Json(name = "server")
val server: FederationGetVersionServer?
)
@JsonClass(generateAdapter = true)
internal data class FederationGetVersionServer(
/**
* Arbitrary name that identify this implementation.
*/

View file

@ -33,8 +33,8 @@ internal class DefaultGetFederationVersionTask @Inject constructor(
}
return FederationVersion(
name = result.name,
version = result.version
name = result.server?.name,
version = result.server?.version
)
}
}

View file

@ -109,6 +109,7 @@ import im.vector.app.features.settings.devtools.GossipingEventsPaperTrailFragmen
import im.vector.app.features.settings.devtools.IncomingKeyRequestListFragment
import im.vector.app.features.settings.devtools.KeyRequestsFragment
import im.vector.app.features.settings.devtools.OutgoingKeyRequestListFragment
import im.vector.app.features.settings.homeserver.HomeserverSettingsFragment
import im.vector.app.features.settings.ignored.VectorSettingsIgnoredUsersFragment
import im.vector.app.features.settings.locale.LocalePickerFragment
import im.vector.app.features.settings.push.PushGatewaysFragment
@ -284,6 +285,11 @@ interface FragmentModule {
@FragmentKey(VectorSettingsLabsFragment::class)
fun bindVectorSettingsLabsFragment(fragment: VectorSettingsLabsFragment): Fragment
@Binds
@IntoMap
@FragmentKey(HomeserverSettingsFragment::class)
fun bindHomeserverSettingsFragment(fragment: HomeserverSettingsFragment): Fragment
@Binds
@IntoMap
@FragmentKey(VectorSettingsPinFragment::class)

View file

@ -0,0 +1,41 @@
/*
* 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.discovery
import android.widget.ImageView
import androidx.annotation.DrawableRes
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import com.airbnb.epoxy.EpoxyModelWithHolder
import im.vector.app.R
import im.vector.app.core.epoxy.VectorEpoxyHolder
@EpoxyModelClass(layout = R.layout.item_settings_centered_image)
abstract class SettingsCenteredImageItem : EpoxyModelWithHolder<SettingsCenteredImageItem.Holder>() {
@EpoxyAttribute
@DrawableRes
var drawableRes: Int = 0
override fun bind(holder: Holder) {
super.bind(holder)
holder.image.setImageResource(drawableRes)
}
class Holder : VectorEpoxyHolder() {
val image by bind<ImageView>(R.id.itemSettingsImage)
}
}

View file

@ -0,0 +1,27 @@
/*
* 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.settings.homeserver
import com.airbnb.mvrx.Async
import com.airbnb.mvrx.MvRxState
import com.airbnb.mvrx.Uninitialized
import org.matrix.android.sdk.api.federation.FederationVersion
data class HomeServerSettingsViewState(
val baseUrl: String = "",
val federationVersion: Async<FederationVersion> = Uninitialized
) : MvRxState

View file

@ -0,0 +1,23 @@
/*
* 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.settings.homeserver
import im.vector.app.core.platform.VectorViewModelAction
sealed class HomeserverSettingsAction : VectorViewModelAction {
object Refresh : HomeserverSettingsAction()
}

View file

@ -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.settings.homeserver
import com.airbnb.epoxy.TypedEpoxyController
import com.airbnb.mvrx.Fail
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.errorWithRetryItem
import im.vector.app.core.epoxy.loadingItem
import im.vector.app.core.error.ErrorFormatter
import im.vector.app.features.discovery.settingsCenteredImageItem
import im.vector.app.features.discovery.settingsInfoItem
import im.vector.app.features.discovery.settingsSectionTitleItem
import org.matrix.android.sdk.api.federation.FederationVersion
import javax.inject.Inject
class HomeserverSettingsController @Inject constructor(
private val errorFormatter: ErrorFormatter
) : TypedEpoxyController<HomeServerSettingsViewState>() {
var callback: Callback? = null
interface Callback {
fun retry()
}
override fun buildModels(data: HomeServerSettingsViewState?) {
data ?: return
buildHeader(data)
when (val federationVersion = data.federationVersion) {
is Loading,
is Uninitialized ->
loadingItem {
id("loading")
}
is Fail ->
errorWithRetryItem {
id("error")
text(errorFormatter.toHumanReadable(federationVersion.error))
listener { callback?.retry() }
}
is Success ->
buildFederationVersion(federationVersion())
}
}
private fun buildHeader(state: HomeServerSettingsViewState) {
settingsCenteredImageItem {
id("icon")
drawableRes(R.drawable.ic_layers)
}
settingsSectionTitleItem {
id("urlTitle")
titleResId(R.string.hs_url)
}
settingsInfoItem {
id("urlValue")
helperText(state.baseUrl)
}
}
private fun buildFederationVersion(federationVersion: FederationVersion) {
settingsSectionTitleItem {
id("nameTitle")
titleResId(R.string.settings_server_name)
}
settingsInfoItem {
id("nameValue")
helperText(federationVersion.name)
}
settingsSectionTitleItem {
id("versionTitle")
titleResId(R.string.settings_server_version)
}
settingsInfoItem {
id("versionValue")
helperText(federationVersion.version)
}
}
}

View file

@ -0,0 +1,73 @@
/*
* 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.settings.homeserver
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import com.airbnb.mvrx.fragmentViewModel
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.VectorBaseFragment
import im.vector.app.databinding.FragmentGenericRecyclerBinding
import javax.inject.Inject
/**
* Display some information about the homeserver
*/
class HomeserverSettingsFragment @Inject constructor(
val homeserverSettingsViewModelFactory: HomeserverSettingsViewModel.Factory,
private val homeserverSettingsController: HomeserverSettingsController
) : VectorBaseFragment<FragmentGenericRecyclerBinding>(),
HomeserverSettingsController.Callback {
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentGenericRecyclerBinding {
return FragmentGenericRecyclerBinding.inflate(inflater, container, false)
}
private val viewModel: HomeserverSettingsViewModel by fragmentViewModel()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
homeserverSettingsController.callback = this
views.genericRecyclerView.configureWith(homeserverSettingsController)
}
override fun onDestroyView() {
homeserverSettingsController.callback = null
views.genericRecyclerView.cleanup()
super.onDestroyView()
}
override fun onResume() {
super.onResume()
(activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.settings_home_server)
}
override fun retry() {
viewModel.handle(HomeserverSettingsAction.Refresh)
}
override fun invalidate() = withState(viewModel) { state ->
homeserverSettingsController.setData(state)
}
}

View file

@ -0,0 +1,92 @@
/*
* 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.settings.homeserver
import androidx.lifecycle.viewModelScope
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.FragmentViewModelContext
import com.airbnb.mvrx.Loading
import com.airbnb.mvrx.MvRxViewModelFactory
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.ViewModelContext
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import im.vector.app.core.platform.EmptyViewEvents
import im.vector.app.core.platform.VectorViewModel
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.session.Session
class HomeserverSettingsViewModel @AssistedInject constructor(
@Assisted initialState: HomeServerSettingsViewState,
private val session: Session
) : VectorViewModel<HomeServerSettingsViewState, HomeserverSettingsAction, EmptyViewEvents>(initialState) {
@AssistedFactory
interface Factory {
fun create(initialState: HomeServerSettingsViewState): HomeserverSettingsViewModel
}
companion object : MvRxViewModelFactory<HomeserverSettingsViewModel, HomeServerSettingsViewState> {
@JvmStatic
override fun create(viewModelContext: ViewModelContext, state: HomeServerSettingsViewState): HomeserverSettingsViewModel? {
val fragment: HomeserverSettingsFragment = (viewModelContext as FragmentViewModelContext).fragment()
return fragment.homeserverSettingsViewModelFactory.create(state)
}
}
init {
setState {
copy(
baseUrl = session.sessionParams.homeServerUrl
)
}
fetchHomeserverVersion()
}
private fun fetchHomeserverVersion() {
setState {
copy(
federationVersion = Loading()
)
}
viewModelScope.launch {
try {
val federationVersion = session.federationService().getFederationVersion()
setState {
copy(
federationVersion = Success(federationVersion)
)
}
} catch (failure: Throwable) {
setState {
copy(
federationVersion = Fail(failure)
)
}
}
}
}
override fun handle(action: HomeserverSettingsAction) {
when (action) {
HomeserverSettingsAction.Refresh -> fetchHomeserverVersion()
}
}
}

View file

@ -0,0 +1,27 @@
<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="#00000000"
android:pathData="M12,2L2,7L12,12L22,7L12,2Z"
android:strokeWidth="2"
android:strokeColor="#000000"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:fillColor="#00000000"
android:pathData="M2,17L12,22L22,17"
android:strokeWidth="2"
android:strokeColor="#000000"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:fillColor="#00000000"
android:pathData="M2,12L12,17L22,12"
android:strokeWidth="2"
android:strokeColor="#000000"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
</vector>

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<ImageView 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/itemSettingsImage"
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_margin="16dp"
android:importantForAccessibility="no"
app:tint="@color/riotx_accent"
tools:src="@drawable/ic_layers" />

View file

@ -2336,6 +2336,9 @@
<string name="settings_active_sessions_manage">Manage Sessions</string>
<string name="settings_active_sessions_signout_device">Sign out of this session</string>
<string name="settings_server_name">Server name</string>
<string name="settings_server_version">Server version</string>
<string name="settings_failed_to_get_crypto_device_info">No cryptographic information available</string>
<string name="settings_active_sessions_verified_device_desc">This session is trusted for secure messaging because you verified it:</string>

View file

@ -81,6 +81,7 @@
<im.vector.app.core.preference.VectorPreference
android:key="SETTINGS_HOME_SERVER_PREFERENCE_KEY"
android:title="@string/settings_home_server"
app:fragment="im.vector.app.features.settings.homeserver.HomeserverSettingsFragment"
tools:summary="https://homeserver.org" />
<im.vector.app.core.preference.VectorPreference