Merge pull request #3322 from vector-im/feature/bca/spaces_feedback
Add option to send beta feedback
This commit is contained in:
commit
b06bd403ca
@ -161,7 +161,7 @@ Formatter\.formatShortFileSize===1
|
|||||||
# android\.text\.TextUtils
|
# android\.text\.TextUtils
|
||||||
|
|
||||||
### This is not a rule, but a warning: the number of "enum class" has changed. For Json classes, it is mandatory that they have `@JsonClass(generateAdapter = false)`. If the enum is not used as a Json class, change the value in file forbidden_strings_in_code.txt
|
### This is not a rule, but a warning: the number of "enum class" has changed. For Json classes, it is mandatory that they have `@JsonClass(generateAdapter = false)`. If the enum is not used as a Json class, change the value in file forbidden_strings_in_code.txt
|
||||||
enum class===99
|
enum class===100
|
||||||
|
|
||||||
### Do not import temporary legacy classes
|
### Do not import temporary legacy classes
|
||||||
import org.matrix.android.sdk.internal.legacy.riot===3
|
import org.matrix.android.sdk.internal.legacy.riot===3
|
||||||
|
@ -16,12 +16,14 @@
|
|||||||
package im.vector.app.core.ui.list
|
package im.vector.app.core.ui.list
|
||||||
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.annotation.ColorInt
|
||||||
import com.airbnb.epoxy.EpoxyAttribute
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
import im.vector.app.core.extensions.setTextOrHide
|
import im.vector.app.core.extensions.setTextOrHide
|
||||||
|
import im.vector.app.features.themes.ThemeUtils
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic list item header left aligned with notice color.
|
* A generic list item header left aligned with notice color.
|
||||||
@ -32,9 +34,18 @@ abstract class GenericItemHeader : VectorEpoxyModel<GenericItemHeader.Holder>()
|
|||||||
@EpoxyAttribute
|
@EpoxyAttribute
|
||||||
var text: String? = null
|
var text: String? = null
|
||||||
|
|
||||||
|
@EpoxyAttribute
|
||||||
|
@ColorInt
|
||||||
|
var textColor: Int? = null
|
||||||
|
|
||||||
override fun bind(holder: Holder) {
|
override fun bind(holder: Holder) {
|
||||||
super.bind(holder)
|
super.bind(holder)
|
||||||
holder.text.setTextOrHide(text)
|
holder.text.setTextOrHide(text)
|
||||||
|
if (textColor != null) {
|
||||||
|
holder.text.setTextColor(textColor!!)
|
||||||
|
} else {
|
||||||
|
holder.text.setTextColor(ThemeUtils.getColor(holder.view.context, R.attr.vctr_notice_text_color))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Holder : VectorEpoxyHolder() {
|
class Holder : VectorEpoxyHolder() {
|
||||||
|
@ -55,6 +55,7 @@ import im.vector.app.features.permalink.PermalinkHandler
|
|||||||
import im.vector.app.features.popup.DefaultVectorAlert
|
import im.vector.app.features.popup.DefaultVectorAlert
|
||||||
import im.vector.app.features.popup.PopupAlertManager
|
import im.vector.app.features.popup.PopupAlertManager
|
||||||
import im.vector.app.features.popup.VerificationVectorAlert
|
import im.vector.app.features.popup.VerificationVectorAlert
|
||||||
|
import im.vector.app.features.rageshake.ReportType
|
||||||
import im.vector.app.features.rageshake.VectorUncaughtExceptionHandler
|
import im.vector.app.features.rageshake.VectorUncaughtExceptionHandler
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
import im.vector.app.features.settings.VectorSettingsActivity
|
import im.vector.app.features.settings.VectorSettingsActivity
|
||||||
@ -216,6 +217,9 @@ class HomeActivity :
|
|||||||
SpaceInviteBottomSheet.newInstance(sharedAction.spaceId)
|
SpaceInviteBottomSheet.newInstance(sharedAction.spaceId)
|
||||||
.show(supportFragmentManager, "SPACE_INVITE")
|
.show(supportFragmentManager, "SPACE_INVITE")
|
||||||
}
|
}
|
||||||
|
HomeActivitySharedAction.SendSpaceFeedBack -> {
|
||||||
|
bugReporter.openBugReportScreen(this, ReportType.SPACE_BETA_FEEDBACK)
|
||||||
|
}
|
||||||
}.exhaustive
|
}.exhaustive
|
||||||
}
|
}
|
||||||
.disposeOnDestroy()
|
.disposeOnDestroy()
|
||||||
@ -449,11 +453,11 @@ class HomeActivity :
|
|||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.menu_home_suggestion -> {
|
R.id.menu_home_suggestion -> {
|
||||||
bugReporter.openBugReportScreen(this, true)
|
bugReporter.openBugReportScreen(this, ReportType.SUGGESTION)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.menu_home_report_bug -> {
|
R.id.menu_home_report_bug -> {
|
||||||
bugReporter.openBugReportScreen(this, false)
|
bugReporter.openBugReportScreen(this, ReportType.BUG_REPORT)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.menu_home_init_sync_legacy -> {
|
R.id.menu_home_init_sync_legacy -> {
|
||||||
|
@ -29,4 +29,5 @@ sealed class HomeActivitySharedAction : VectorSharedAction {
|
|||||||
data class OpenSpacePreview(val spaceId: String) : HomeActivitySharedAction()
|
data class OpenSpacePreview(val spaceId: String) : HomeActivitySharedAction()
|
||||||
data class OpenSpaceInvite(val spaceId: String) : HomeActivitySharedAction()
|
data class OpenSpaceInvite(val spaceId: String) : HomeActivitySharedAction()
|
||||||
data class ShowSpaceSettings(val spaceId: String) : HomeActivitySharedAction()
|
data class ShowSpaceSettings(val spaceId: String) : HomeActivitySharedAction()
|
||||||
|
object SendSpaceFeedBack : HomeActivitySharedAction()
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package im.vector.app.features.rageshake
|
package im.vector.app.features.rageshake
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
@ -27,6 +29,7 @@ import im.vector.app.R
|
|||||||
import im.vector.app.core.di.ScreenComponent
|
import im.vector.app.core.di.ScreenComponent
|
||||||
import im.vector.app.core.platform.VectorBaseActivity
|
import im.vector.app.core.platform.VectorBaseActivity
|
||||||
import im.vector.app.databinding.ActivityBugReportBinding
|
import im.vector.app.databinding.ActivityBugReportBinding
|
||||||
|
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||||
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -46,7 +49,7 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
|
|||||||
|
|
||||||
private val viewModel: BugReportViewModel by viewModel()
|
private val viewModel: BugReportViewModel by viewModel()
|
||||||
|
|
||||||
private var forSuggestion: Boolean = false
|
private var reportType: ReportType = ReportType.BUG_REPORT
|
||||||
|
|
||||||
override fun initUiAndData() {
|
override fun initUiAndData() {
|
||||||
configureToolbar(views.bugReportToolbar)
|
configureToolbar(views.bugReportToolbar)
|
||||||
@ -60,15 +63,38 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
|
|||||||
views.bugReportButtonIncludeScreenshot.isEnabled = false
|
views.bugReportButtonIncludeScreenshot.isEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
forSuggestion = intent.getBooleanExtra("FOR_SUGGESTION", false)
|
reportType = intent.getStringExtra(REPORT_TYPE_EXTRA)?.let {
|
||||||
|
tryOrNull { ReportType.valueOf(it) }
|
||||||
|
} ?: ReportType.BUG_REPORT
|
||||||
|
|
||||||
// Default screen is for bug report, so modify it for suggestion
|
// Default screen is for bug report, so modify it for suggestion
|
||||||
if (forSuggestion) {
|
when (reportType) {
|
||||||
|
ReportType.BUG_REPORT -> {
|
||||||
|
supportActionBar?.setTitle(R.string.title_activity_bug_report)
|
||||||
|
views.bugReportButtonContactMe.isVisible = true
|
||||||
|
}
|
||||||
|
ReportType.SUGGESTION -> {
|
||||||
supportActionBar?.setTitle(R.string.send_suggestion)
|
supportActionBar?.setTitle(R.string.send_suggestion)
|
||||||
|
|
||||||
views.bugReportFirstText.setText(R.string.send_suggestion_content)
|
views.bugReportFirstText.setText(R.string.send_suggestion_content)
|
||||||
views.bugReportTextInputLayout.hint = getString(R.string.send_suggestion_report_placeholder)
|
views.bugReportTextInputLayout.hint = getString(R.string.send_suggestion_report_placeholder)
|
||||||
|
views.bugReportButtonContactMe.isVisible = true
|
||||||
|
|
||||||
|
hideBugReportOptions()
|
||||||
|
}
|
||||||
|
ReportType.SPACE_BETA_FEEDBACK -> {
|
||||||
|
supportActionBar?.setTitle(R.string.send_feedback_space_title)
|
||||||
|
|
||||||
|
views.bugReportFirstText.setText(R.string.send_feedback_space_info)
|
||||||
|
views.bugReportTextInputLayout.hint = getString(R.string.feedback)
|
||||||
|
views.bugReportButtonContactMe.isVisible = true
|
||||||
|
|
||||||
|
hideBugReportOptions()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hideBugReportOptions() {
|
||||||
views.bugReportLogsDescription.isVisible = false
|
views.bugReportLogsDescription.isVisible = false
|
||||||
|
|
||||||
views.bugReportButtonIncludeLogs.isChecked = false
|
views.bugReportButtonIncludeLogs.isChecked = false
|
||||||
@ -79,11 +105,6 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
|
|||||||
|
|
||||||
views.bugReportButtonIncludeKeyShareHistory.isChecked = false
|
views.bugReportButtonIncludeKeyShareHistory.isChecked = false
|
||||||
views.bugReportButtonIncludeKeyShareHistory.isVisible = false
|
views.bugReportButtonIncludeKeyShareHistory.isVisible = false
|
||||||
|
|
||||||
// Keep the screenshot
|
|
||||||
} else {
|
|
||||||
supportActionBar?.setTitle(R.string.title_activity_bug_report)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupViews() {
|
private fun setupViews() {
|
||||||
@ -134,24 +155,32 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
|
|||||||
views.bugReportProgressView.progress = 0
|
views.bugReportProgressView.progress = 0
|
||||||
|
|
||||||
bugReporter.sendBugReport(this,
|
bugReporter.sendBugReport(this,
|
||||||
forSuggestion,
|
reportType,
|
||||||
views.bugReportButtonIncludeLogs.isChecked,
|
views.bugReportButtonIncludeLogs.isChecked,
|
||||||
views.bugReportButtonIncludeCrashLogs.isChecked,
|
views.bugReportButtonIncludeCrashLogs.isChecked,
|
||||||
views.bugReportButtonIncludeKeyShareHistory.isChecked,
|
views.bugReportButtonIncludeKeyShareHistory.isChecked,
|
||||||
views.bugReportButtonIncludeScreenshot.isChecked,
|
views.bugReportButtonIncludeScreenshot.isChecked,
|
||||||
views.bugReportEditText.text.toString(),
|
views.bugReportEditText.text.toString(),
|
||||||
state.serverVersion,
|
state.serverVersion,
|
||||||
|
views.bugReportButtonContactMe.isChecked,
|
||||||
object : BugReporter.IMXBugReportListener {
|
object : BugReporter.IMXBugReportListener {
|
||||||
override fun onUploadFailed(reason: String?) {
|
override fun onUploadFailed(reason: String?) {
|
||||||
try {
|
try {
|
||||||
if (!reason.isNullOrEmpty()) {
|
if (!reason.isNullOrEmpty()) {
|
||||||
if (forSuggestion) {
|
when (reportType) {
|
||||||
Toast.makeText(this@BugReportActivity,
|
ReportType.BUG_REPORT -> {
|
||||||
getString(R.string.send_suggestion_failed, reason), Toast.LENGTH_LONG).show()
|
|
||||||
} else {
|
|
||||||
Toast.makeText(this@BugReportActivity,
|
Toast.makeText(this@BugReportActivity,
|
||||||
getString(R.string.send_bug_report_failed, reason), Toast.LENGTH_LONG).show()
|
getString(R.string.send_bug_report_failed, reason), Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
|
ReportType.SUGGESTION -> {
|
||||||
|
Toast.makeText(this@BugReportActivity,
|
||||||
|
getString(R.string.send_suggestion_failed, reason), Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
ReportType.SPACE_BETA_FEEDBACK -> {
|
||||||
|
Toast.makeText(this@BugReportActivity,
|
||||||
|
getString(R.string.feedback_failed, reason), Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "## onUploadFailed() : failed to display the toast")
|
Timber.e(e, "## onUploadFailed() : failed to display the toast")
|
||||||
@ -178,11 +207,17 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
|
|||||||
|
|
||||||
override fun onUploadSucceed() {
|
override fun onUploadSucceed() {
|
||||||
try {
|
try {
|
||||||
if (forSuggestion) {
|
when (reportType) {
|
||||||
Toast.makeText(this@BugReportActivity, R.string.send_suggestion_sent, Toast.LENGTH_LONG).show()
|
ReportType.BUG_REPORT -> {
|
||||||
} else {
|
|
||||||
Toast.makeText(this@BugReportActivity, R.string.send_bug_report_sent, Toast.LENGTH_LONG).show()
|
Toast.makeText(this@BugReportActivity, R.string.send_bug_report_sent, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
|
ReportType.SUGGESTION -> {
|
||||||
|
Toast.makeText(this@BugReportActivity, R.string.send_suggestion_sent, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
ReportType.SPACE_BETA_FEEDBACK -> {
|
||||||
|
Toast.makeText(this@BugReportActivity, R.string.feedback_sent, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "## onUploadSucceed() : failed to dismiss the toast")
|
Timber.e(e, "## onUploadSucceed() : failed to dismiss the toast")
|
||||||
}
|
}
|
||||||
@ -214,4 +249,14 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
|
|||||||
|
|
||||||
super.onBackPressed()
|
super.onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val REPORT_TYPE_EXTRA = "REPORT_TYPE_EXTRA"
|
||||||
|
|
||||||
|
fun intent(context: Context, reportType: ReportType): Intent {
|
||||||
|
return Intent(context, BugReportActivity::class.java).apply {
|
||||||
|
putExtra(REPORT_TYPE_EXTRA, reportType.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ package im.vector.app.features.rageshake
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
@ -149,7 +148,7 @@ class BugReporter @Inject constructor(
|
|||||||
* Send a bug report.
|
* Send a bug report.
|
||||||
*
|
*
|
||||||
* @param context the application context
|
* @param context the application context
|
||||||
* @param forSuggestion true to send a suggestion
|
* @param reportType The report type (bug, suggestion, feedback)
|
||||||
* @param withDevicesLogs true to include the device log
|
* @param withDevicesLogs true to include the device log
|
||||||
* @param withCrashLogs true to include the crash logs
|
* @param withCrashLogs true to include the crash logs
|
||||||
* @param withKeyRequestHistory true to include the crash logs
|
* @param withKeyRequestHistory true to include the crash logs
|
||||||
@ -159,13 +158,14 @@ class BugReporter @Inject constructor(
|
|||||||
*/
|
*/
|
||||||
@SuppressLint("StaticFieldLeak")
|
@SuppressLint("StaticFieldLeak")
|
||||||
fun sendBugReport(context: Context,
|
fun sendBugReport(context: Context,
|
||||||
forSuggestion: Boolean,
|
reportType: ReportType,
|
||||||
withDevicesLogs: Boolean,
|
withDevicesLogs: Boolean,
|
||||||
withCrashLogs: Boolean,
|
withCrashLogs: Boolean,
|
||||||
withKeyRequestHistory: Boolean,
|
withKeyRequestHistory: Boolean,
|
||||||
withScreenshot: Boolean,
|
withScreenshot: Boolean,
|
||||||
theBugDescription: String,
|
theBugDescription: String,
|
||||||
serverVersion: String,
|
serverVersion: String,
|
||||||
|
canContact: Boolean = false,
|
||||||
listener: IMXBugReportListener?) {
|
listener: IMXBugReportListener?) {
|
||||||
// enumerate files to delete
|
// enumerate files to delete
|
||||||
val mBugReportFiles: MutableList<File> = ArrayList()
|
val mBugReportFiles: MutableList<File> = ArrayList()
|
||||||
@ -246,13 +246,11 @@ class BugReporter @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!mIsCancelled) {
|
if (!mIsCancelled) {
|
||||||
val text = "[Element] " +
|
val text = when (reportType) {
|
||||||
if (forSuggestion) {
|
ReportType.BUG_REPORT -> "[Element] $bugDescription"
|
||||||
"[Suggestion] "
|
ReportType.SUGGESTION -> "[Element] [Suggestion] $bugDescription"
|
||||||
} else {
|
ReportType.SPACE_BETA_FEEDBACK -> "[Element] [spaces-feedback] $bugDescription"
|
||||||
""
|
}
|
||||||
} +
|
|
||||||
bugDescription
|
|
||||||
|
|
||||||
// build the multi part request
|
// build the multi part request
|
||||||
val builder = BugReporterMultipartBody.Builder()
|
val builder = BugReporterMultipartBody.Builder()
|
||||||
@ -260,6 +258,7 @@ class BugReporter @Inject constructor(
|
|||||||
.addFormDataPart("app", "riot-android")
|
.addFormDataPart("app", "riot-android")
|
||||||
.addFormDataPart("user_agent", Matrix.getInstance(context).getUserAgent())
|
.addFormDataPart("user_agent", Matrix.getInstance(context).getUserAgent())
|
||||||
.addFormDataPart("user_id", userId)
|
.addFormDataPart("user_id", userId)
|
||||||
|
.addFormDataPart("can_contact", canContact.toString())
|
||||||
.addFormDataPart("device_id", deviceId)
|
.addFormDataPart("device_id", deviceId)
|
||||||
.addFormDataPart("version", versionProvider.getVersion(longFormat = true, useBuildNumber = false))
|
.addFormDataPart("version", versionProvider.getVersion(longFormat = true, useBuildNumber = false))
|
||||||
.addFormDataPart("branch_name", context.getString(R.string.git_branch_name))
|
.addFormDataPart("branch_name", context.getString(R.string.git_branch_name))
|
||||||
@ -321,9 +320,12 @@ class BugReporter @Inject constructor(
|
|||||||
// Special for RiotX
|
// Special for RiotX
|
||||||
builder.addFormDataPart("label", "[Element]")
|
builder.addFormDataPart("label", "[Element]")
|
||||||
|
|
||||||
// Suggestion
|
when (reportType) {
|
||||||
if (forSuggestion) {
|
ReportType.BUG_REPORT -> {
|
||||||
builder.addFormDataPart("label", "[Suggestion]")
|
/* nop */
|
||||||
|
}
|
||||||
|
ReportType.SUGGESTION -> builder.addFormDataPart("label", "[Suggestion]")
|
||||||
|
ReportType.SPACE_BETA_FEEDBACK -> builder.addFormDataPart("label", "spaces-feedback")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getCrashFile(context).exists()) {
|
if (getCrashFile(context).exists()) {
|
||||||
@ -447,16 +449,14 @@ class BugReporter @Inject constructor(
|
|||||||
/**
|
/**
|
||||||
* Send a bug report either with email or with Vector.
|
* Send a bug report either with email or with Vector.
|
||||||
*/
|
*/
|
||||||
fun openBugReportScreen(activity: FragmentActivity, forSuggestion: Boolean = false) {
|
fun openBugReportScreen(activity: FragmentActivity, reportType: ReportType = ReportType.BUG_REPORT) {
|
||||||
screenshot = takeScreenshot(activity)
|
screenshot = takeScreenshot(activity)
|
||||||
activeSessionHolder.getSafeActiveSession()?.let {
|
activeSessionHolder.getSafeActiveSession()?.let {
|
||||||
it.logDbUsageInfo()
|
it.logDbUsageInfo()
|
||||||
it.cryptoService().logDbUsageInfo()
|
it.cryptoService().logDbUsageInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
val intent = Intent(activity, BugReportActivity::class.java)
|
activity.startActivity(BugReportActivity.intent(activity, reportType))
|
||||||
intent.putExtra("FOR_SUGGESTION", forSuggestion)
|
|
||||||
activity.startActivity(intent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==============================================================================================================
|
// ==============================================================================================================
|
||||||
|
@ -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.rageshake
|
||||||
|
|
||||||
|
enum class ReportType {
|
||||||
|
BUG_REPORT,
|
||||||
|
SUGGESTION,
|
||||||
|
SPACE_BETA_FEEDBACK
|
||||||
|
}
|
@ -16,13 +16,28 @@
|
|||||||
|
|
||||||
package im.vector.app.features.spaces
|
package im.vector.app.features.spaces
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import com.airbnb.epoxy.EpoxyAttribute
|
||||||
import com.airbnb.epoxy.EpoxyModelClass
|
import com.airbnb.epoxy.EpoxyModelClass
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||||
|
import im.vector.app.core.utils.DebouncedClickListener
|
||||||
|
|
||||||
@EpoxyModelClass(layout = R.layout.item_space_beta_header)
|
@EpoxyModelClass(layout = R.layout.item_space_beta_header)
|
||||||
abstract class SpaceBetaHeaderItem : VectorEpoxyModel<SpaceBetaHeaderItem.Holder>() {
|
abstract class SpaceBetaHeaderItem : VectorEpoxyModel<SpaceBetaHeaderItem.Holder>() {
|
||||||
|
|
||||||
class Holder : VectorEpoxyHolder()
|
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
|
||||||
|
var clickAction: View.OnClickListener? = null
|
||||||
|
|
||||||
|
override fun bind(holder: Holder) {
|
||||||
|
super.bind(holder)
|
||||||
|
holder.feedBackAction.setOnClickListener(DebouncedClickListener({
|
||||||
|
clickAction?.onClick(it)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
class Holder : VectorEpoxyHolder() {
|
||||||
|
val feedBackAction by bind<View>(R.id.spaceBetaFeedbackAction)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,4 +101,8 @@ class SpaceListFragment @Inject constructor(
|
|||||||
override fun onGroupSelected(groupSummary: GroupSummary?) {
|
override fun onGroupSelected(groupSummary: GroupSummary?) {
|
||||||
viewModel.handle(SpaceListAction.SelectLegacyGroup(groupSummary))
|
viewModel.handle(SpaceListAction.SelectLegacyGroup(groupSummary))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun sendFeedBack() {
|
||||||
|
sharedActionViewModel.post(HomeActivitySharedAction.SendSpaceFeedBack)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,8 @@ import im.vector.app.databinding.BottomSheetSpaceSettingsBinding
|
|||||||
import im.vector.app.features.home.AvatarRenderer
|
import im.vector.app.features.home.AvatarRenderer
|
||||||
import im.vector.app.features.navigation.Navigator
|
import im.vector.app.features.navigation.Navigator
|
||||||
import im.vector.app.features.powerlevel.PowerLevelsObservableFactory
|
import im.vector.app.features.powerlevel.PowerLevelsObservableFactory
|
||||||
|
import im.vector.app.features.rageshake.BugReporter
|
||||||
|
import im.vector.app.features.rageshake.ReportType
|
||||||
import im.vector.app.features.roomprofile.RoomProfileActivity
|
import im.vector.app.features.roomprofile.RoomProfileActivity
|
||||||
import im.vector.app.features.settings.VectorPreferences
|
import im.vector.app.features.settings.VectorPreferences
|
||||||
import im.vector.app.features.spaces.manage.ManageType
|
import im.vector.app.features.spaces.manage.ManageType
|
||||||
@ -58,6 +60,7 @@ class SpaceSettingsMenuBottomSheet : VectorBaseBottomSheetDialogFragment<BottomS
|
|||||||
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
|
||||||
@Inject lateinit var avatarRenderer: AvatarRenderer
|
@Inject lateinit var avatarRenderer: AvatarRenderer
|
||||||
@Inject lateinit var vectorPreferences: VectorPreferences
|
@Inject lateinit var vectorPreferences: VectorPreferences
|
||||||
|
@Inject lateinit var bugReporter: BugReporter
|
||||||
|
|
||||||
private val spaceArgs: SpaceBottomSheetSettingsArgs by args()
|
private val spaceArgs: SpaceBottomSheetSettingsArgs by args()
|
||||||
|
|
||||||
@ -106,6 +109,10 @@ class SpaceSettingsMenuBottomSheet : VectorBaseBottomSheetDialogFragment<BottomS
|
|||||||
views.addRooms.isVisible = canAddChild
|
views.addRooms.isVisible = canAddChild
|
||||||
}.disposeOnDestroyView()
|
}.disposeOnDestroyView()
|
||||||
|
|
||||||
|
views.spaceBetaTag.setOnClickListener {
|
||||||
|
bugReporter.openBugReportScreen(requireActivity(), ReportType.SPACE_BETA_FEEDBACK)
|
||||||
|
}
|
||||||
|
|
||||||
views.invitePeople.views.bottomSheetActionClickableZone.debouncedClicks {
|
views.invitePeople.views.bottomSheetActionClickableZone.debouncedClicks {
|
||||||
dismiss()
|
dismiss()
|
||||||
interactionListener?.onShareSpaceSelected(spaceArgs.spaceId)
|
interactionListener?.onShareSpaceSelected(spaceArgs.spaceId)
|
||||||
|
@ -16,9 +16,11 @@
|
|||||||
|
|
||||||
package im.vector.app.features.spaces
|
package im.vector.app.features.spaces
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
import com.airbnb.epoxy.EpoxyController
|
import com.airbnb.epoxy.EpoxyController
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.RoomGroupingMethod
|
import im.vector.app.RoomGroupingMethod
|
||||||
|
import im.vector.app.core.resources.ColorProvider
|
||||||
import im.vector.app.core.resources.StringProvider
|
import im.vector.app.core.resources.StringProvider
|
||||||
import im.vector.app.core.ui.list.genericFooterItem
|
import im.vector.app.core.ui.list.genericFooterItem
|
||||||
import im.vector.app.core.ui.list.genericItemHeader
|
import im.vector.app.core.ui.list.genericItemHeader
|
||||||
@ -38,6 +40,7 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
class SpaceSummaryController @Inject constructor(
|
class SpaceSummaryController @Inject constructor(
|
||||||
private val avatarRenderer: AvatarRenderer,
|
private val avatarRenderer: AvatarRenderer,
|
||||||
|
private val colorProvider: ColorProvider,
|
||||||
private val stringProvider: StringProvider) : EpoxyController() {
|
private val stringProvider: StringProvider) : EpoxyController() {
|
||||||
|
|
||||||
var callback: Callback? = null
|
var callback: Callback? = null
|
||||||
@ -72,6 +75,7 @@ class SpaceSummaryController @Inject constructor(
|
|||||||
genericItemHeader {
|
genericItemHeader {
|
||||||
id("legacy_groups")
|
id("legacy_groups")
|
||||||
text(stringProvider.getString(R.string.groups_header))
|
text(stringProvider.getString(R.string.groups_header))
|
||||||
|
textColor(colorProvider.getColorFromAttribute(R.attr.riotx_text_primary))
|
||||||
}
|
}
|
||||||
|
|
||||||
// add home for communities
|
// add home for communities
|
||||||
@ -104,13 +108,13 @@ class SpaceSummaryController @Inject constructor(
|
|||||||
rootSpaces: List<RoomSummary>?,
|
rootSpaces: List<RoomSummary>?,
|
||||||
expandedStates: Map<String, Boolean>,
|
expandedStates: Map<String, Boolean>,
|
||||||
homeCount: RoomAggregateNotificationCount) {
|
homeCount: RoomAggregateNotificationCount) {
|
||||||
genericItemHeader {
|
spaceBetaHeaderItem {
|
||||||
id("spaces")
|
id("beta_header")
|
||||||
text(stringProvider.getString(R.string.spaces_header))
|
clickAction(View.OnClickListener {
|
||||||
|
callback?.sendFeedBack()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
spaceBetaHeaderItem { id("beta_header") }
|
|
||||||
|
|
||||||
// show invites on top
|
// show invites on top
|
||||||
|
|
||||||
summaries?.filter { it.membership == Membership.INVITE }
|
summaries?.filter { it.membership == Membership.INVITE }
|
||||||
@ -221,7 +225,7 @@ class SpaceSummaryController @Inject constructor(
|
|||||||
fun onSpaceSettings(spaceSummary: RoomSummary)
|
fun onSpaceSettings(spaceSummary: RoomSummary)
|
||||||
fun onToggleExpand(spaceSummary: RoomSummary)
|
fun onToggleExpand(spaceSummary: RoomSummary)
|
||||||
fun onAddSpaceSelected()
|
fun onAddSpaceSelected()
|
||||||
|
|
||||||
fun onGroupSelected(groupSummary: GroupSummary?)
|
fun onGroupSelected(groupSummary: GroupSummary?)
|
||||||
|
fun sendFeedBack()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
vector/src/main/res/drawable/ic_feedback.xml
Normal file
14
vector/src/main/res/drawable/ic_feedback.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="16dp"
|
||||||
|
android:height="16dp"
|
||||||
|
android:viewportWidth="16"
|
||||||
|
android:viewportHeight="16">
|
||||||
|
<path
|
||||||
|
android:pathData="M6.2887,10.748C8.7036,10.748 10.6612,8.7897 10.6612,6.374C10.6612,3.9583 8.7036,2 6.2887,2C3.8739,2 1.9163,3.9583 1.9163,6.374C1.9163,7.038 2.0642,7.6674 2.3288,8.2311L1.6,9.7683C1.2011,10.6099 2.0682,11.492 2.9165,11.1074L4.5258,10.378C5.0651,10.6159 5.6615,10.748 6.2887,10.748Z"
|
||||||
|
android:fillColor="#368BD6"
|
||||||
|
android:fillType="evenOdd"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M12.6608,7.3739C12.6608,9.7896 10.7032,11.7479 8.2883,11.7479C7.8421,11.7479 7.4114,11.681 7.0059,11.5568C7.7732,12.2953 8.8076,12.7479 9.9456,12.7479C10.5605,12.7479 11.1451,12.6158 11.6737,12.3778L13.211,13.0887C14.0564,13.4796 14.9301,12.6043 14.5376,11.7597L13.8272,10.2308C14.0865,9.6672 14.2315,9.0378 14.2315,8.3739C14.2315,6.4535 13.0188,4.8221 11.3323,4.2339C12.1516,5.0289 12.6608,6.1419 12.6608,7.3739Z"
|
||||||
|
android:fillColor="#368BD6"
|
||||||
|
android:fillType="evenOdd"/>
|
||||||
|
</vector>
|
@ -133,6 +133,15 @@
|
|||||||
android:checked="false"
|
android:checked="false"
|
||||||
android:text="@string/send_bug_report_include_key_share_history" />
|
android:text="@string/send_bug_report_include_key_share_history" />
|
||||||
|
|
||||||
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
|
android:id="@+id/bug_report_button_contact_me"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
android:checked="false"
|
||||||
|
android:text="@string/you_may_contact_me" />
|
||||||
|
|
||||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
android:id="@+id/bug_report_button_include_screenshot"
|
android:id="@+id/bug_report_button_include_screenshot"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
android:layout_marginStart="@dimen/layout_horizontal_margin"
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:duplicateParentState="true"
|
android:duplicateParentState="true"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
@ -39,12 +38,22 @@
|
|||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
app:layout_constrainedWidth="true"
|
app:layout_constrainedWidth="true"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/spaceDescription"
|
app:layout_constraintBottom_toTopOf="@+id/spaceDescription"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toStartOf="@id/spaceBetaTag"
|
||||||
app:layout_constraintStart_toEndOf="@id/spaceAvatarImageView"
|
app:layout_constraintStart_toEndOf="@id/spaceAvatarImageView"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:layout_constraintVertical_chainStyle="packed"
|
app:layout_constraintVertical_chainStyle="packed"
|
||||||
tools:text="@sample/matrix.json/data/displayName" />
|
tools:text="@sample/matrix.json/data/displayName" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/spaceBetaTag"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:contentDescription="@string/a11y_beta"
|
||||||
|
android:src="@drawable/ic_beta_pill"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/spaceDescription"
|
android:id="@+id/spaceDescription"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@ -97,7 +106,7 @@
|
|||||||
app:actionTitle="@string/settings"
|
app:actionTitle="@string/settings"
|
||||||
app:leftIcon="@drawable/ic_settings_root_general"
|
app:leftIcon="@drawable/ic_settings_root_general"
|
||||||
app:tint="?attr/riotx_text_primary"
|
app:tint="?attr/riotx_text_primary"
|
||||||
app:titleTextColor="?attr/riotx_text_primary"/>
|
app:titleTextColor="?attr/riotx_text_primary" />
|
||||||
|
|
||||||
<im.vector.app.core.ui.views.BottomSheetActionButton
|
<im.vector.app.core.ui.views.BottomSheetActionButton
|
||||||
android:id="@+id/exploreRooms"
|
android:id="@+id/exploreRooms"
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="@dimen/layout_vertical_margin_big"
|
android:layout_marginTop="@dimen/layout_vertical_margin_big"
|
||||||
android:importantForAccessibility="no"
|
android:contentDescription="@string/a11y_beta"
|
||||||
android:src="@drawable/ic_beta_pill"
|
android:src="@drawable/ic_beta_pill"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
@ -1,47 +1,43 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="16dp">
|
android:orientation="vertical"
|
||||||
|
android:paddingStart="16dp"
|
||||||
<FrameLayout
|
android:paddingTop="8dp"
|
||||||
android:layout_width="match_parent"
|
android:paddingEnd="16dp">
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@drawable/rounded_rect_stroke_8"
|
|
||||||
android:padding="8dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
android:src="@drawable/ic_beta_pill" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:text="@string/spaces_beta_welcome_to_spaces"
|
android:text="@string/spaces_header"
|
||||||
android:textColor="?riotx_text_primary"
|
android:textColor="?riotx_text_primary"
|
||||||
android:textSize="15sp"
|
android:textSize="15sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold"
|
||||||
|
app:drawableEndCompat="@drawable/ic_beta_pill" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:text="@string/spaces_beta_welcome_to_spaces_desc"
|
android:text="@string/spaces_beta_welcome_to_spaces_desc"
|
||||||
android:textColor="?riotx_text_secondary"
|
android:textColor="?riotx_text_secondary"
|
||||||
android:textSize="15sp" />
|
android:textSize="15sp" />
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</FrameLayout>
|
<TextView
|
||||||
|
android:id="@+id/spaceBetaFeedbackAction"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawablePadding="8dp"
|
||||||
|
android:paddingStart="0dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:text="@string/give_feedback"
|
||||||
|
android:textColor="@color/vector_info_color"
|
||||||
|
android:textSize="15sp"
|
||||||
|
app:drawableStartCompat="@drawable/ic_feedback" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
</FrameLayout>
|
|
||||||
|
@ -2167,6 +2167,14 @@
|
|||||||
<string name="send_suggestion_sent">Thanks, the suggestion has been successfully sent</string>
|
<string name="send_suggestion_sent">Thanks, the suggestion has been successfully sent</string>
|
||||||
<string name="send_suggestion_failed">The suggestion failed to be sent (%s)</string>
|
<string name="send_suggestion_failed">The suggestion failed to be sent (%s)</string>
|
||||||
|
|
||||||
|
<string name="send_feedback_space_title">Spaces feedback</string>
|
||||||
|
<string name="feedback">Feedback</string>
|
||||||
|
<string name="send_feedback_space_info">You’re using a beta version of spaces. Your feedback will help inform the next versions. Your platform and username will be noted to help us use your feedback as much as we can.</string>
|
||||||
|
<string name="you_may_contact_me">You may contact me if you have any follow up questions</string>
|
||||||
|
<string name="feedback_sent">Thanks, your feedback has been successfully sent</string>
|
||||||
|
<string name="feedback_failed">The feedback failed to be sent (%s)</string>
|
||||||
|
<string name="give_feedback">Give Feedback</string>
|
||||||
|
|
||||||
<string name="settings_labs_show_hidden_events_in_timeline">Show hidden events in timeline</string>
|
<string name="settings_labs_show_hidden_events_in_timeline">Show hidden events in timeline</string>
|
||||||
<string name="settings_labs_show_complete_history_in_encrypted_room">"Show complete history in encrypted rooms"</string>
|
<string name="settings_labs_show_complete_history_in_encrypted_room">"Show complete history in encrypted rooms"</string>
|
||||||
|
|
||||||
@ -2286,6 +2294,7 @@
|
|||||||
<string name="a11y_show_password">Show password</string>
|
<string name="a11y_show_password">Show password</string>
|
||||||
<string name="a11y_hide_password">Hide password</string>
|
<string name="a11y_hide_password">Hide password</string>
|
||||||
<string name="a11y_jump_to_bottom">Jump to bottom</string>
|
<string name="a11y_jump_to_bottom">Jump to bottom</string>
|
||||||
|
<string name="a11y_beta">This feature is in beta</string>
|
||||||
|
|
||||||
<!-- Read receipts list a11y -->
|
<!-- Read receipts list a11y -->
|
||||||
<plurals name="two_and_some_others_read">
|
<plurals name="two_and_some_others_read">
|
||||||
@ -3347,7 +3356,7 @@
|
|||||||
|
|
||||||
<string name="space_add_existing_rooms">Add existing rooms and space</string>
|
<string name="space_add_existing_rooms">Add existing rooms and space</string>
|
||||||
<string name="spaces_beta_welcome_to_spaces">Welcome to Spaces!</string>
|
<string name="spaces_beta_welcome_to_spaces">Welcome to Spaces!</string>
|
||||||
<string name="spaces_beta_welcome_to_spaces_desc">Spaces are ways to group rooms and people for work, fun or just yourself.</string>
|
<string name="spaces_beta_welcome_to_spaces_desc">Spaces are a new way to group rooms and people.</string>
|
||||||
<string name="you_are_invited">You are invited</string>
|
<string name="you_are_invited">You are invited</string>
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user