mirror of
https://github.com/vector-im/element-android.git
synced 2024-11-15 01:35:07 +08:00
commit
34898f1c81
1
changelog.d/4638.feature
Normal file
1
changelog.d/4638.feature
Normal file
@ -0,0 +1 @@
|
||||
Add a help section in the settings.
|
1
changelog.d/4660.feature
Normal file
1
changelog.d/4660.feature
Normal file
@ -0,0 +1 @@
|
||||
Create a legal screen in the setting to group all the different policies.
|
@ -16,6 +16,8 @@
|
||||
|
||||
package org.matrix.android.sdk.api.session.terms
|
||||
|
||||
import org.matrix.android.sdk.internal.session.terms.TermsResponse
|
||||
|
||||
interface TermsService {
|
||||
enum class ServiceType {
|
||||
IntegrationManager,
|
||||
@ -28,4 +30,10 @@ interface TermsService {
|
||||
baseUrl: String,
|
||||
agreedUrls: List<String>,
|
||||
token: String?)
|
||||
|
||||
/**
|
||||
* Get the homeserver terms, from the register API.
|
||||
* Will be updated once https://github.com/matrix-org/matrix-doc/pull/3012 will be implemented.
|
||||
*/
|
||||
suspend fun getHomeserverTerms(baseUrl: String): TermsResponse
|
||||
}
|
||||
|
@ -18,10 +18,13 @@ package org.matrix.android.sdk.internal.session.terms
|
||||
|
||||
import dagger.Lazy
|
||||
import okhttp3.OkHttpClient
|
||||
import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
|
||||
import org.matrix.android.sdk.api.failure.toRegistrationFlowResponse
|
||||
import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
|
||||
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||
import org.matrix.android.sdk.api.session.terms.GetTermsResponse
|
||||
import org.matrix.android.sdk.api.session.terms.TermsService
|
||||
import org.matrix.android.sdk.api.util.JsonDict
|
||||
import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate
|
||||
import org.matrix.android.sdk.internal.network.NetworkConstants
|
||||
import org.matrix.android.sdk.internal.network.RetrofitFactory
|
||||
@ -55,6 +58,27 @@ internal class DefaultTermsService @Inject constructor(
|
||||
return GetTermsResponse(termsResponse, getAlreadyAcceptedTermUrlsFromAccountData())
|
||||
}
|
||||
|
||||
/**
|
||||
* We use a trick here to get the homeserver T&C, we use the register API
|
||||
*/
|
||||
override suspend fun getHomeserverTerms(baseUrl: String): TermsResponse {
|
||||
return try {
|
||||
executeRequest(null) {
|
||||
termsAPI.register(baseUrl + NetworkConstants.URI_API_PREFIX_PATH_R0 + "register")
|
||||
}
|
||||
// Return empty result if it succeed, but it should never happen
|
||||
TermsResponse()
|
||||
} catch (throwable: Throwable) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
TermsResponse(
|
||||
policies = (throwable.toRegistrationFlowResponse()
|
||||
?.params
|
||||
?.get(LoginFlowTypes.TERMS) as? JsonDict)
|
||||
?.get("policies") as? JsonDict
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun agreeToTerms(serviceType: TermsService.ServiceType,
|
||||
baseUrl: String,
|
||||
agreedUrls: List<String>,
|
||||
@ -91,7 +115,7 @@ internal class DefaultTermsService @Inject constructor(
|
||||
private fun buildUrl(baseUrl: String, serviceType: TermsService.ServiceType): String {
|
||||
val servicePath = when (serviceType) {
|
||||
TermsService.ServiceType.IntegrationManager -> NetworkConstants.URI_INTEGRATION_MANAGER_PATH
|
||||
TermsService.ServiceType.IdentityService -> NetworkConstants.URI_IDENTITY_PATH_V2
|
||||
TermsService.ServiceType.IdentityService -> NetworkConstants.URI_IDENTITY_PATH_V2
|
||||
}
|
||||
return "${baseUrl.ensureTrailingSlash()}$servicePath"
|
||||
}
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
package org.matrix.android.sdk.internal.session.terms
|
||||
|
||||
import org.matrix.android.sdk.api.util.JsonDict
|
||||
import org.matrix.android.sdk.api.util.emptyJsonDict
|
||||
import org.matrix.android.sdk.internal.network.HttpHeaders
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.GET
|
||||
@ -37,4 +39,12 @@ internal interface TermsAPI {
|
||||
suspend fun agreeToTerms(@Url url: String,
|
||||
@Body params: AcceptTermsBody,
|
||||
@Header(HttpHeaders.Authorization) token: String)
|
||||
|
||||
/**
|
||||
* API to retrieve the terms for a homeserver. The API /terms does not exist yet, so retrieve the terms from the login flow.
|
||||
* We do not care about the result (Credentials)
|
||||
*/
|
||||
@POST
|
||||
suspend fun register(@Url url: String,
|
||||
@Body body: JsonDict = emptyJsonDict)
|
||||
}
|
||||
|
@ -133,6 +133,7 @@ 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.legals.LegalsFragment
|
||||
import im.vector.app.features.settings.locale.LocalePickerFragment
|
||||
import im.vector.app.features.settings.notifications.VectorSettingsAdvancedNotificationPreferenceFragment
|
||||
import im.vector.app.features.settings.notifications.VectorSettingsNotificationPreferenceFragment
|
||||
@ -699,6 +700,11 @@ interface FragmentModule {
|
||||
@FragmentKey(DiscoverySettingsFragment::class)
|
||||
fun bindDiscoverySettingsFragment(fragment: DiscoverySettingsFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(LegalsFragment::class)
|
||||
fun bindLegalsFragment(fragment: LegalsFragment): Fragment
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@FragmentKey(ReviewTermsFragment::class)
|
||||
|
@ -85,6 +85,7 @@ import im.vector.app.features.settings.devtools.KeyRequestListViewModel
|
||||
import im.vector.app.features.settings.devtools.KeyRequestViewModel
|
||||
import im.vector.app.features.settings.homeserver.HomeserverSettingsViewModel
|
||||
import im.vector.app.features.settings.ignored.IgnoredUsersViewModel
|
||||
import im.vector.app.features.settings.legals.LegalsViewModel
|
||||
import im.vector.app.features.settings.locale.LocalePickerViewModel
|
||||
import im.vector.app.features.settings.push.PushGatewaysViewModel
|
||||
import im.vector.app.features.settings.threepids.ThreePidsSettingsViewModel
|
||||
@ -504,6 +505,11 @@ interface MavericksViewModelModule {
|
||||
@MavericksViewModelKey(DiscoverySettingsViewModel::class)
|
||||
fun discoverySettingsViewModelFactory(factory: DiscoverySettingsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@MavericksViewModelKey(LegalsViewModel::class)
|
||||
fun legalsViewModelFactory(factory: LegalsViewModel.Factory): MavericksAssistedViewModelFactory<*, *>
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@MavericksViewModelKey(RoomDetailViewModel::class)
|
||||
|
@ -23,7 +23,7 @@ import android.webkit.WebViewClient
|
||||
import android.widget.TextView
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import im.vector.app.R
|
||||
import im.vector.app.features.discovery.IdentityServerWithTerms
|
||||
import im.vector.app.features.discovery.ServerAndPolicies
|
||||
import me.gujun.android.span.link
|
||||
import me.gujun.android.span.span
|
||||
|
||||
@ -45,7 +45,7 @@ fun Context.displayInWebView(url: String) {
|
||||
.show()
|
||||
}
|
||||
|
||||
fun Context.showIdentityServerConsentDialog(identityServerWithTerms: IdentityServerWithTerms?,
|
||||
fun Context.showIdentityServerConsentDialog(identityServerWithTerms: ServerAndPolicies?,
|
||||
consentCallBack: (() -> Unit)) {
|
||||
// Build the message
|
||||
val content = span {
|
||||
|
@ -17,9 +17,9 @@
|
||||
package im.vector.app.features.contactsbook
|
||||
|
||||
import im.vector.app.core.platform.VectorViewEvents
|
||||
import im.vector.app.features.discovery.IdentityServerWithTerms
|
||||
import im.vector.app.features.discovery.ServerAndPolicies
|
||||
|
||||
sealed class ContactsBookViewEvents : VectorViewEvents {
|
||||
data class Failure(val throwable: Throwable) : ContactsBookViewEvents()
|
||||
data class OnPoliciesRetrieved(val identityServerWithTerms: IdentityServerWithTerms?) : ContactsBookViewEvents()
|
||||
data class OnPoliciesRetrieved(val identityServerWithTerms: ServerAndPolicies?) : ContactsBookViewEvents()
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ 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.extensions.setTextOrHide
|
||||
|
||||
@EpoxyModelClass(layout = R.layout.item_discovery_policy)
|
||||
abstract class DiscoveryPolicyItem : EpoxyModelWithHolder<DiscoveryPolicyItem.Holder>() {
|
||||
@ -40,7 +41,7 @@ abstract class DiscoveryPolicyItem : EpoxyModelWithHolder<DiscoveryPolicyItem.Ho
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
holder.title.text = name
|
||||
holder.url.text = url
|
||||
holder.url.setTextOrHide(url)
|
||||
holder.view.onClick(clickListener)
|
||||
}
|
||||
|
||||
|
@ -433,6 +433,6 @@ class DiscoverySettingsController @Inject constructor(
|
||||
fun onTapUpdateUserConsent(newValue: Boolean)
|
||||
fun onTapRetryToRetrieveBindings()
|
||||
fun onPolicyUrlsExpandedStateToggled(newExpandedState: Boolean)
|
||||
fun onPolicyTapped(policy: IdentityServerPolicy)
|
||||
fun onPolicyTapped(policy: ServerPolicy)
|
||||
}
|
||||
}
|
||||
|
@ -167,10 +167,11 @@ class DiscoverySettingsFragment @Inject constructor(
|
||||
val pidList = state.emailList().orEmpty() + state.phoneNumbersList().orEmpty()
|
||||
val hasBoundIds = pidList.any { it.isShared() == SharedState.SHARED }
|
||||
|
||||
val serverUrl = state.identityServer()?.serverUrl.orEmpty()
|
||||
val message = if (hasBoundIds) {
|
||||
getString(R.string.settings_discovery_disconnect_with_bound_pid, state.identityServer(), state.identityServer())
|
||||
getString(R.string.settings_discovery_disconnect_with_bound_pid, serverUrl, serverUrl)
|
||||
} else {
|
||||
getString(R.string.disconnect_identity_server_dialog_content, state.identityServer())
|
||||
getString(R.string.disconnect_identity_server_dialog_content, serverUrl)
|
||||
}
|
||||
|
||||
MaterialAlertDialogBuilder(requireActivity())
|
||||
@ -203,7 +204,7 @@ class DiscoverySettingsFragment @Inject constructor(
|
||||
viewModel.handle(DiscoverySettingsAction.SetPoliciesExpandState(expanded = newExpandedState))
|
||||
}
|
||||
|
||||
override fun onPolicyTapped(policy: IdentityServerPolicy) {
|
||||
override fun onPolicyTapped(policy: ServerPolicy) {
|
||||
openUrlInChromeCustomTab(requireContext(), null, policy.url)
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ import com.airbnb.mvrx.MavericksState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
|
||||
data class DiscoverySettingsState(
|
||||
val identityServer: Async<IdentityServerWithTerms?> = Uninitialized,
|
||||
val identityServer: Async<ServerAndPolicies?> = Uninitialized,
|
||||
val emailList: Async<List<PidInfo>> = Uninitialized,
|
||||
val phoneNumbersList: Async<List<PidInfo>> = Uninitialized,
|
||||
// Can be true if terms are updated
|
||||
|
@ -78,7 +78,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
|
||||
init {
|
||||
setState {
|
||||
copy(
|
||||
identityServer = Success(identityService.getCurrentIdentityServerUrl()?.let { IdentityServerWithTerms(it, emptyList()) }),
|
||||
identityServer = Success(identityService.getCurrentIdentityServerUrl()?.let { ServerAndPolicies(it, emptyList()) }),
|
||||
userConsent = identityService.getUserConsent()
|
||||
)
|
||||
}
|
||||
@ -151,7 +151,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
|
||||
val data = session.identityService().setNewIdentityServer(action.url)
|
||||
setState {
|
||||
copy(
|
||||
identityServer = Success(IdentityServerWithTerms(data, emptyList())),
|
||||
identityServer = Success(ServerAndPolicies(data, emptyList())),
|
||||
userConsent = false
|
||||
)
|
||||
}
|
||||
@ -401,7 +401,7 @@ class DiscoverySettingsViewModel @AssistedInject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun fetchIdentityServerWithTerms(): IdentityServerWithTerms? {
|
||||
private suspend fun fetchIdentityServerWithTerms(): ServerAndPolicies? {
|
||||
return session.fetchIdentityServerWithTerms(stringProvider.getString(R.string.resources_language))
|
||||
}
|
||||
}
|
||||
|
@ -19,22 +19,35 @@ package im.vector.app.features.discovery
|
||||
import im.vector.app.core.utils.ensureProtocol
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
import org.matrix.android.sdk.api.session.terms.TermsService
|
||||
import org.matrix.android.sdk.internal.session.terms.TermsResponse
|
||||
|
||||
suspend fun Session.fetchIdentityServerWithTerms(userLanguage: String): IdentityServerWithTerms? {
|
||||
val identityServerUrl = identityService().getCurrentIdentityServerUrl()
|
||||
return identityServerUrl?.let {
|
||||
val terms = getTerms(TermsService.ServiceType.IdentityService, identityServerUrl.ensureProtocol())
|
||||
.serverResponse
|
||||
.getLocalizedTerms(userLanguage)
|
||||
val policyUrls = terms.mapNotNull {
|
||||
val name = it.localizedName ?: it.policyName
|
||||
val url = it.localizedUrl
|
||||
if (name == null || url == null) {
|
||||
null
|
||||
} else {
|
||||
IdentityServerPolicy(name = name, url = url)
|
||||
suspend fun Session.fetchIdentityServerWithTerms(userLanguage: String): ServerAndPolicies? {
|
||||
return identityService().getCurrentIdentityServerUrl()
|
||||
?.let { identityServerUrl ->
|
||||
val termsResponse = getTerms(TermsService.ServiceType.IdentityService, identityServerUrl.ensureProtocol())
|
||||
.serverResponse
|
||||
buildServerAndPolicies(identityServerUrl, termsResponse, userLanguage)
|
||||
}
|
||||
}
|
||||
IdentityServerWithTerms(identityServerUrl, policyUrls)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun Session.fetchHomeserverWithTerms(userLanguage: String): ServerAndPolicies {
|
||||
val homeserverUrl = sessionParams.homeServerUrl
|
||||
val terms = getHomeserverTerms(homeserverUrl.ensureProtocol())
|
||||
return buildServerAndPolicies(homeserverUrl, terms, userLanguage)
|
||||
}
|
||||
|
||||
private fun buildServerAndPolicies(serviceUrl: String,
|
||||
termsResponse: TermsResponse,
|
||||
userLanguage: String): ServerAndPolicies {
|
||||
val terms = termsResponse.getLocalizedTerms(userLanguage)
|
||||
val policyUrls = terms.mapNotNull {
|
||||
val name = it.localizedName ?: it.policyName
|
||||
val url = it.localizedUrl
|
||||
if (name == null || url == null) {
|
||||
null
|
||||
} else {
|
||||
ServerPolicy(name = name, url = url)
|
||||
}
|
||||
}
|
||||
return ServerAndPolicies(serviceUrl, policyUrls)
|
||||
}
|
||||
|
@ -16,12 +16,12 @@
|
||||
|
||||
package im.vector.app.features.discovery
|
||||
|
||||
data class IdentityServerWithTerms(
|
||||
data class ServerAndPolicies(
|
||||
val serverUrl: String,
|
||||
val policies: List<IdentityServerPolicy>
|
||||
val policies: List<ServerPolicy>
|
||||
)
|
||||
|
||||
data class IdentityServerPolicy(
|
||||
data class ServerPolicy(
|
||||
val name: String,
|
||||
val url: String
|
||||
)
|
@ -35,6 +35,7 @@ import javax.inject.Inject
|
||||
class VectorPreferences @Inject constructor(private val context: Context) {
|
||||
|
||||
companion object {
|
||||
const val SETTINGS_HELP_PREFERENCE_KEY = "SETTINGS_HELP_PREFERENCE_KEY"
|
||||
const val SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY = "SETTINGS_CHANGE_PASSWORD_PREFERENCE_KEY"
|
||||
const val SETTINGS_VERSION_PREFERENCE_KEY = "SETTINGS_VERSION_PREFERENCE_KEY"
|
||||
const val SETTINGS_SDK_VERSION_PREFERENCE_KEY = "SETTINGS_SDK_VERSION_PREFERENCE_KEY"
|
||||
@ -42,13 +43,8 @@ class VectorPreferences @Inject constructor(private val context: Context) {
|
||||
const val SETTINGS_LOGGED_IN_PREFERENCE_KEY = "SETTINGS_LOGGED_IN_PREFERENCE_KEY"
|
||||
const val SETTINGS_HOME_SERVER_PREFERENCE_KEY = "SETTINGS_HOME_SERVER_PREFERENCE_KEY"
|
||||
const val SETTINGS_IDENTITY_SERVER_PREFERENCE_KEY = "SETTINGS_IDENTITY_SERVER_PREFERENCE_KEY"
|
||||
const val SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY = "SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY"
|
||||
const val SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY = "SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY"
|
||||
const val SETTINGS_DISCOVERY_PREFERENCE_KEY = "SETTINGS_DISCOVERY_PREFERENCE_KEY"
|
||||
|
||||
const val SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY = "SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY"
|
||||
const val SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY = "SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY"
|
||||
const val SETTINGS_COPYRIGHT_PREFERENCE_KEY = "SETTINGS_COPYRIGHT_PREFERENCE_KEY"
|
||||
const val SETTINGS_CLEAR_CACHE_PREFERENCE_KEY = "SETTINGS_CLEAR_CACHE_PREFERENCE_KEY"
|
||||
const val SETTINGS_CLEAR_MEDIA_CACHE_PREFERENCE_KEY = "SETTINGS_CLEAR_MEDIA_CACHE_PREFERENCE_KEY"
|
||||
const val SETTINGS_USER_SETTINGS_PREFERENCE_KEY = "SETTINGS_USER_SETTINGS_PREFERENCE_KEY"
|
||||
|
@ -22,11 +22,9 @@ import im.vector.app.R
|
||||
import im.vector.app.core.preference.VectorPreference
|
||||
import im.vector.app.core.utils.FirstThrottler
|
||||
import im.vector.app.core.utils.copyToClipboard
|
||||
import im.vector.app.core.utils.displayInWebView
|
||||
import im.vector.app.core.utils.openAppSettingsPage
|
||||
import im.vector.app.core.utils.openUrlInChromeCustomTab
|
||||
import im.vector.app.features.version.VersionProvider
|
||||
import im.vector.app.openOssLicensesMenuActivity
|
||||
import org.matrix.android.sdk.api.Matrix
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -40,6 +38,15 @@ class VectorSettingsHelpAboutFragment @Inject constructor(
|
||||
private val firstThrottler = FirstThrottler(1000)
|
||||
|
||||
override fun bindPref() {
|
||||
// Help
|
||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_HELP_PREFERENCE_KEY)!!
|
||||
.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
if (firstThrottler.canHandle() is FirstThrottler.CanHandlerResult.Yes) {
|
||||
openUrlInChromeCustomTab(requireContext(), null, VectorSettingsUrls.HELP)
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
// preference to start the App info screen, to facilitate App permissions access
|
||||
findPreference<VectorPreference>(APP_INFO_LINK_PREFERENCE_KEY)!!
|
||||
.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
@ -76,44 +83,6 @@ class VectorSettingsHelpAboutFragment @Inject constructor(
|
||||
// olm version
|
||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_OLM_VERSION_PREFERENCE_KEY)!!
|
||||
.summary = session.cryptoService().getCryptoVersion(requireContext(), false)
|
||||
|
||||
// copyright
|
||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_COPYRIGHT_PREFERENCE_KEY)!!
|
||||
.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
openUrlInChromeCustomTab(requireContext(), null, VectorSettingsUrls.COPYRIGHT)
|
||||
false
|
||||
}
|
||||
|
||||
// terms & conditions
|
||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY)!!
|
||||
.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
openUrlInChromeCustomTab(requireContext(), null, VectorSettingsUrls.TAC)
|
||||
false
|
||||
}
|
||||
|
||||
// privacy policy
|
||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY)!!
|
||||
.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
openUrlInChromeCustomTab(requireContext(), null, VectorSettingsUrls.PRIVACY_POLICY)
|
||||
false
|
||||
}
|
||||
|
||||
// third party notice
|
||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY)!!
|
||||
.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
if (firstThrottler.canHandle() is FirstThrottler.CanHandlerResult.Yes) {
|
||||
activity?.displayInWebView(VectorSettingsUrls.THIRD_PARTY_LICENSES)
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
// Note: preference is not visible on F-Droid build
|
||||
findPreference<VectorPreference>(VectorPreferences.SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY)!!
|
||||
.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
// See https://developers.google.com/android/guides/opensource
|
||||
openOssLicensesMenuActivity(requireActivity())
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -17,7 +17,7 @@
|
||||
package im.vector.app.features.settings
|
||||
|
||||
object VectorSettingsUrls {
|
||||
|
||||
const val HELP = "https://element.io/help"
|
||||
const val COPYRIGHT = "https://element.io/copyright"
|
||||
const val TAC = "https://element.io/terms-of-service"
|
||||
const val PRIVACY_POLICY = "https://element.io/privacy"
|
||||
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.legals
|
||||
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import im.vector.app.features.discovery.ServerPolicy
|
||||
import im.vector.app.features.settings.VectorSettingsUrls
|
||||
import javax.inject.Inject
|
||||
|
||||
class ElementLegals @Inject constructor(
|
||||
private val stringProvider: StringProvider
|
||||
) {
|
||||
/**
|
||||
* Use ServerPolicy model
|
||||
*/
|
||||
fun getData(): List<ServerPolicy> {
|
||||
return listOf(
|
||||
ServerPolicy(stringProvider.getString(R.string.settings_copyright), VectorSettingsUrls.COPYRIGHT),
|
||||
ServerPolicy(stringProvider.getString(R.string.settings_app_term_conditions), VectorSettingsUrls.TAC),
|
||||
ServerPolicy(stringProvider.getString(R.string.settings_privacy_policy), VectorSettingsUrls.PRIVACY_POLICY)
|
||||
)
|
||||
}
|
||||
}
|
@ -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.legals
|
||||
|
||||
import im.vector.app.core.platform.VectorViewModelAction
|
||||
|
||||
sealed interface LegalsAction : VectorViewModelAction {
|
||||
object Refresh : LegalsAction
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* 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.legals
|
||||
|
||||
import android.content.res.Resources
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import com.airbnb.mvrx.Async
|
||||
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.core.resources.StringProvider
|
||||
import im.vector.app.features.discovery.ServerAndPolicies
|
||||
import im.vector.app.features.discovery.ServerPolicy
|
||||
import im.vector.app.features.discovery.discoveryPolicyItem
|
||||
import im.vector.app.features.discovery.settingsInfoItem
|
||||
import im.vector.app.features.discovery.settingsSectionTitleItem
|
||||
import javax.inject.Inject
|
||||
|
||||
class LegalsController @Inject constructor(
|
||||
private val stringProvider: StringProvider,
|
||||
private val resources: Resources,
|
||||
private val elementLegals: ElementLegals,
|
||||
private val errorFormatter: ErrorFormatter
|
||||
) : TypedEpoxyController<LegalsState>() {
|
||||
|
||||
var listener: Listener? = null
|
||||
|
||||
override fun buildModels(data: LegalsState) {
|
||||
buildAppSection()
|
||||
buildHomeserverSection(data)
|
||||
buildIdentityServerSection(data)
|
||||
buildThirdPartyNotices()
|
||||
}
|
||||
|
||||
private fun buildAppSection() {
|
||||
settingsSectionTitleItem {
|
||||
id("appTitle")
|
||||
titleResId(R.string.legals_application_title)
|
||||
}
|
||||
|
||||
buildPolicies("el", elementLegals.getData())
|
||||
}
|
||||
|
||||
private fun buildHomeserverSection(data: LegalsState) {
|
||||
settingsSectionTitleItem {
|
||||
id("hsServerTitle")
|
||||
titleResId(R.string.legals_home_server_title)
|
||||
}
|
||||
|
||||
buildPolicyAsync("hs", data.homeServer)
|
||||
}
|
||||
|
||||
private fun buildIdentityServerSection(data: LegalsState) {
|
||||
if (data.hasIdentityServer) {
|
||||
settingsSectionTitleItem {
|
||||
id("idServerTitle")
|
||||
titleResId(R.string.legals_identity_server_title)
|
||||
}
|
||||
|
||||
buildPolicyAsync("is", data.identityServer)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildPolicyAsync(tag: String, serverAndPolicies: Async<ServerAndPolicies?>) {
|
||||
val host = this
|
||||
|
||||
when (serverAndPolicies) {
|
||||
Uninitialized,
|
||||
is Loading -> loadingItem {
|
||||
id("loading_$tag")
|
||||
}
|
||||
is Success -> {
|
||||
val policies = serverAndPolicies()?.policies
|
||||
if (policies.isNullOrEmpty()) {
|
||||
settingsInfoItem {
|
||||
id("emptyPolicy")
|
||||
helperText(host.stringProvider.getString(R.string.legals_no_policy_provided))
|
||||
}
|
||||
} else {
|
||||
buildPolicies(tag, policies)
|
||||
}
|
||||
}
|
||||
is Fail -> {
|
||||
errorWithRetryItem {
|
||||
id("errorRetry_$tag")
|
||||
text(host.errorFormatter.toHumanReadable(serverAndPolicies.error))
|
||||
listener { host.listener?.onTapRetry() }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildPolicies(tag: String, policies: List<ServerPolicy>) {
|
||||
val host = this
|
||||
|
||||
policies.forEach { policy ->
|
||||
discoveryPolicyItem {
|
||||
id(tag + policy.url)
|
||||
name(policy.name)
|
||||
url(policy.url.takeIf { it.startsWith("http") })
|
||||
clickListener { host.listener?.openPolicy(policy) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildThirdPartyNotices() {
|
||||
val host = this
|
||||
settingsSectionTitleItem {
|
||||
id("thirdTitle")
|
||||
titleResId(R.string.legals_third_party_notices)
|
||||
}
|
||||
|
||||
discoveryPolicyItem {
|
||||
id("eltpn1")
|
||||
name(host.stringProvider.getString(R.string.settings_third_party_notices))
|
||||
clickListener { host.listener?.openThirdPartyNotice() }
|
||||
}
|
||||
// Only on Gplay
|
||||
if (resources.getBoolean(R.bool.isGplay)) {
|
||||
discoveryPolicyItem {
|
||||
id("eltpn2")
|
||||
name(host.stringProvider.getString(R.string.settings_other_third_party_notices))
|
||||
clickListener { host.listener?.openThirdPartyNoticeGplay() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
fun onTapRetry()
|
||||
fun openPolicy(policy: ServerPolicy)
|
||||
fun openThirdPartyNotice()
|
||||
fun openThirdPartyNoticeGplay()
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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.legals
|
||||
|
||||
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.core.utils.FirstThrottler
|
||||
import im.vector.app.core.utils.displayInWebView
|
||||
import im.vector.app.core.utils.openUrlInChromeCustomTab
|
||||
import im.vector.app.databinding.FragmentGenericRecyclerBinding
|
||||
import im.vector.app.features.discovery.ServerPolicy
|
||||
import im.vector.app.features.settings.VectorSettingsUrls
|
||||
import im.vector.app.openOssLicensesMenuActivity
|
||||
import javax.inject.Inject
|
||||
|
||||
class LegalsFragment @Inject constructor(
|
||||
private val controller: LegalsController
|
||||
) : VectorBaseFragment<FragmentGenericRecyclerBinding>(),
|
||||
LegalsController.Listener {
|
||||
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentGenericRecyclerBinding {
|
||||
return FragmentGenericRecyclerBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
private val viewModel by fragmentViewModel(LegalsViewModel::class)
|
||||
private val firstThrottler = FirstThrottler(1000)
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
controller.listener = this
|
||||
views.genericRecyclerView.configureWith(controller)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
views.genericRecyclerView.cleanup()
|
||||
controller.listener = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) { state ->
|
||||
controller.setData(state)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
(activity as? AppCompatActivity)?.supportActionBar?.setTitle(R.string.preference_root_legals)
|
||||
viewModel.handle(LegalsAction.Refresh)
|
||||
}
|
||||
|
||||
override fun onTapRetry() {
|
||||
viewModel.handle(LegalsAction.Refresh)
|
||||
}
|
||||
|
||||
override fun openPolicy(policy: ServerPolicy) {
|
||||
openUrl(policy.url)
|
||||
}
|
||||
|
||||
override fun openThirdPartyNotice() {
|
||||
openUrl(VectorSettingsUrls.THIRD_PARTY_LICENSES)
|
||||
}
|
||||
|
||||
private fun openUrl(url: String) {
|
||||
if (firstThrottler.canHandle() is FirstThrottler.CanHandlerResult.Yes) {
|
||||
if (url.startsWith("file://")) {
|
||||
activity?.displayInWebView(url)
|
||||
} else {
|
||||
openUrlInChromeCustomTab(requireContext(), null, url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun openThirdPartyNoticeGplay() {
|
||||
if (firstThrottler.canHandle() is FirstThrottler.CanHandlerResult.Yes) {
|
||||
// See https://developers.google.com/android/guides/opensource
|
||||
openOssLicensesMenuActivity(requireActivity())
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.legals
|
||||
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.MavericksState
|
||||
import com.airbnb.mvrx.Uninitialized
|
||||
import im.vector.app.features.discovery.ServerAndPolicies
|
||||
|
||||
data class LegalsState(
|
||||
val homeServer: Async<ServerAndPolicies?> = Uninitialized,
|
||||
val hasIdentityServer: Boolean = false,
|
||||
val identityServer: Async<ServerAndPolicies?> = Uninitialized
|
||||
) : MavericksState
|
@ -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.legals
|
||||
|
||||
import com.airbnb.mvrx.Fail
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.MavericksViewModelFactory
|
||||
import com.airbnb.mvrx.Success
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
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.core.resources.StringProvider
|
||||
import im.vector.app.features.discovery.fetchHomeserverWithTerms
|
||||
import im.vector.app.features.discovery.fetchIdentityServerWithTerms
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.session.Session
|
||||
|
||||
class LegalsViewModel @AssistedInject constructor(
|
||||
@Assisted initialState: LegalsState,
|
||||
private val session: Session,
|
||||
private val stringProvider: StringProvider
|
||||
) : VectorViewModel<LegalsState, LegalsAction, EmptyViewEvents>(initialState) {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : MavericksAssistedViewModelFactory<LegalsViewModel, LegalsState> {
|
||||
override fun create(initialState: LegalsState): LegalsViewModel
|
||||
}
|
||||
|
||||
companion object : MavericksViewModelFactory<LegalsViewModel, LegalsState> by hiltMavericksViewModelFactory()
|
||||
|
||||
override fun handle(action: LegalsAction) {
|
||||
when (action) {
|
||||
LegalsAction.Refresh -> loadData()
|
||||
}.exhaustive
|
||||
}
|
||||
|
||||
private fun loadData() = withState { state ->
|
||||
loadHomeserver(state)
|
||||
val url = session.identityService().getCurrentIdentityServerUrl()
|
||||
if (url.isNullOrEmpty()) {
|
||||
setState { copy(hasIdentityServer = false) }
|
||||
} else {
|
||||
setState { copy(hasIdentityServer = true) }
|
||||
loadIdentityServer(state)
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadHomeserver(state: LegalsState) {
|
||||
if (state.homeServer !is Success) {
|
||||
setState { copy(homeServer = Loading()) }
|
||||
viewModelScope.launch {
|
||||
runCatching { session.fetchHomeserverWithTerms(stringProvider.getString(R.string.resources_language)) }
|
||||
.fold(
|
||||
onSuccess = { setState { copy(homeServer = Success(it)) } },
|
||||
onFailure = { setState { copy(homeServer = Fail(it)) } }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadIdentityServer(state: LegalsState) {
|
||||
if (state.identityServer !is Success) {
|
||||
setState { copy(identityServer = Loading()) }
|
||||
viewModelScope.launch {
|
||||
runCatching { session.fetchIdentityServerWithTerms(stringProvider.getString(R.string.resources_language)) }
|
||||
.fold(
|
||||
onSuccess = { setState { copy(identityServer = Success(it)) } },
|
||||
onFailure = { setState { copy(identityServer = Fail(it)) } }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -17,13 +17,13 @@
|
||||
package im.vector.app.features.userdirectory
|
||||
|
||||
import im.vector.app.core.platform.VectorViewEvents
|
||||
import im.vector.app.features.discovery.IdentityServerWithTerms
|
||||
import im.vector.app.features.discovery.ServerAndPolicies
|
||||
|
||||
/**
|
||||
* Transient events for invite users to room screen
|
||||
*/
|
||||
sealed class UserListViewEvents : VectorViewEvents {
|
||||
data class Failure(val throwable: Throwable) : UserListViewEvents()
|
||||
data class OnPoliciesRetrieved(val identityServerWithTerms: IdentityServerWithTerms?) : UserListViewEvents()
|
||||
data class OnPoliciesRetrieved(val identityServerWithTerms: ServerAndPolicies?) : UserListViewEvents()
|
||||
data class OpenShareMatrixToLink(val link: String) : UserListViewEvents()
|
||||
}
|
||||
|
10
vector/src/main/res/drawable/ic_settings_root_legals.xml
Normal file
10
vector/src/main/res/drawable/ic_settings_root_legals.xml
Normal file
@ -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:fillColor="#000000"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M4,5C4,3.3431 5.3432,2 7,2H17C18.6569,2 20,3.3431 20,5V19C20,20.6569 18.6569,22 17,22H7C5.3432,22 4,20.6569 4,19V5ZM7,14.25C7,13.8358 7.3358,13.5 7.75,13.5H16.25C16.6642,13.5 17,13.8358 17,14.25C17,14.6642 16.6642,15 16.25,15H7.75C7.3358,15 7,14.6642 7,14.25ZM7.75,17C7.3358,17 7,17.3358 7,17.75C7,18.1642 7.3358,18.5 7.75,18.5H12.25C12.6642,18.5 13,18.1642 13,17.75C13,17.3358 12.6642,17 12.25,17H7.75Z" />
|
||||
</vector>
|
@ -5,8 +5,20 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:minHeight="80dp"
|
||||
android:padding="16dp">
|
||||
|
||||
<androidx.constraintlayout.helper.widget.Flow
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:constraint_referenced_ids="discovery_policy_name,discovery_policy_url"
|
||||
app:flow_verticalGap="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/discovery_policy_arrow"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/discovery_policy_name"
|
||||
style="@style/Widget.Vector.TextView.Body"
|
||||
@ -16,10 +28,7 @@
|
||||
android:paddingEnd="8dp"
|
||||
android:textColor="?vctr_content_primary"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toStartOf="@id/discovery_policy_arrow"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Integration manager" />
|
||||
tools:text="Copyright" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/discovery_policy_url"
|
||||
@ -28,11 +37,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:textColor="?vctr_content_secondary"
|
||||
app:layout_constraintEnd_toStartOf="@id/discovery_policy_arrow"
|
||||
app:layout_constraintStart_toStartOf="@id/discovery_policy_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/discovery_policy_name"
|
||||
tools:text="Use bots, bridges, widget and sticker packs." />
|
||||
android:textColor="?android:textColorLink"
|
||||
tools:text="https://element.io/copyright" />
|
||||
|
||||
<!-- Do not use drawableEnd on the TextView because of RTL support -->
|
||||
<ImageView
|
||||
|
@ -1397,6 +1397,12 @@
|
||||
<string name="settings_integration_allow">Allow integrations</string>
|
||||
<string name="settings_integration_manager">Integration manager</string>
|
||||
|
||||
<string name="template_legals_application_title">${app_name} policy</string>
|
||||
<string name="legals_home_server_title">Your homeserver policy</string>
|
||||
<string name="legals_identity_server_title">Your identity server policy</string>
|
||||
<string name="legals_third_party_notices">Third party libraries</string>
|
||||
<string name="legals_no_policy_provided">This server does not provide any policy.</string>
|
||||
|
||||
<string name="disabled_integration_dialog_title">Integrations are disabled</string>
|
||||
<string name="disabled_integration_dialog_content">"Enable 'Allow integrations' in Settings to do this."</string>
|
||||
|
||||
@ -2270,7 +2276,13 @@
|
||||
|
||||
<string name="preference_voice_and_video">Voice & Video</string>
|
||||
<string name="preference_root_help_about">Help & About</string>
|
||||
<string name="preference_root_legals">Legals</string>
|
||||
|
||||
<string name="preference_help">Help</string>
|
||||
<string name="preference_help_title">Help and support</string>
|
||||
<string name="preference_help_summary">Get help with using Element</string>
|
||||
<string name="preference_versions">Versions</string>
|
||||
<string name="preference_system_settings">System settings</string>
|
||||
|
||||
<string name="settings_troubleshoot_test_token_registration_quick_fix">Register token</string>
|
||||
|
||||
@ -3566,7 +3578,6 @@
|
||||
<string name="space_manage_rooms_and_spaces">Manage rooms and spaces</string>
|
||||
|
||||
|
||||
|
||||
<string name="preference_show_all_rooms_in_home">Show all rooms in Home</string>
|
||||
<string name="all_rooms_youre_in_will_be_shown_in_home">All rooms you’re in will be shown in Home.</string>
|
||||
|
||||
|
@ -1,47 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.preference.PreferenceScreen 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">
|
||||
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="APP_INFO_LINK_PREFERENCE_KEY"
|
||||
android:summary="@string/settings_app_info_link_summary"
|
||||
android:title="@string/settings_app_info_link_title" />
|
||||
<im.vector.app.core.preference.VectorPreferenceCategory android:title="@string/preference_help">
|
||||
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="SETTINGS_VERSION_PREFERENCE_KEY"
|
||||
android:title="@string/settings_version"
|
||||
tools:summary="1.2.3" />
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="SETTINGS_HELP_PREFERENCE_KEY"
|
||||
android:summary="@string/preference_help_summary"
|
||||
android:title="@string/preference_help_title" />
|
||||
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="SETTINGS_SDK_VERSION_PREFERENCE_KEY"
|
||||
android:title="@string/settings_sdk_version"
|
||||
tools:summary="4.5.6" />
|
||||
</im.vector.app.core.preference.VectorPreferenceCategory>
|
||||
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="SETTINGS_OLM_VERSION_PREFERENCE_KEY"
|
||||
android:title="@string/settings_olm_version"
|
||||
tools:summary="7.8.9" />
|
||||
<im.vector.app.core.preference.VectorPreferenceCategory android:title="@string/preference_versions">
|
||||
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="SETTINGS_COPYRIGHT_PREFERENCE_KEY"
|
||||
android:title="@string/settings_copyright" />
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="SETTINGS_VERSION_PREFERENCE_KEY"
|
||||
android:title="@string/settings_version"
|
||||
tools:summary="1.2.3" />
|
||||
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="SETTINGS_APP_TERM_CONDITIONS_PREFERENCE_KEY"
|
||||
android:title="@string/settings_app_term_conditions" />
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="SETTINGS_SDK_VERSION_PREFERENCE_KEY"
|
||||
android:title="@string/settings_sdk_version"
|
||||
tools:summary="4.5.6" />
|
||||
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="SETTINGS_PRIVACY_POLICY_PREFERENCE_KEY"
|
||||
android:title="@string/settings_privacy_policy" />
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="SETTINGS_OLM_VERSION_PREFERENCE_KEY"
|
||||
android:title="@string/settings_olm_version"
|
||||
tools:summary="7.8.9" />
|
||||
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="SETTINGS_THIRD_PARTY_NOTICES_PREFERENCE_KEY"
|
||||
android:title="@string/settings_third_party_notices" />
|
||||
</im.vector.app.core.preference.VectorPreferenceCategory>
|
||||
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="SETTINGS_OTHER_THIRD_PARTY_NOTICES_PREFERENCE_KEY"
|
||||
android:title="@string/settings_other_third_party_notices"
|
||||
app:isPreferenceVisible="@bool/isGplay" />
|
||||
<im.vector.app.core.preference.VectorPreferenceCategory android:title="@string/preference_system_settings">
|
||||
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:key="APP_INFO_LINK_PREFERENCE_KEY"
|
||||
android:summary="@string/settings_app_info_link_summary"
|
||||
android:title="@string/settings_app_info_link_title" />
|
||||
|
||||
</im.vector.app.core.preference.VectorPreferenceCategory>
|
||||
|
||||
</androidx.preference.PreferenceScreen>
|
@ -53,4 +53,9 @@
|
||||
android:title="@string/preference_root_help_about"
|
||||
app:fragment="im.vector.app.features.settings.VectorSettingsHelpAboutFragment" />
|
||||
|
||||
<im.vector.app.core.preference.VectorPreference
|
||||
android:icon="@drawable/ic_settings_root_legals"
|
||||
android:title="@string/preference_root_legals"
|
||||
app:fragment="im.vector.app.features.settings.legals.LegalsFragment" />
|
||||
|
||||
</androidx.preference.PreferenceScreen>
|
Loading…
Reference in New Issue
Block a user