Merge branch 'develop' into feat/polls-max-selections

This commit is contained in:
Benoit Marty
2026-08-07 14:03:17 +02:00
committed by GitHub
4915 changed files with 74016 additions and 22432 deletions
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<plurals name="a11y_polls_percent_of_total">
<item quantity="one">"%1$d% af de samlede stemmer"</item>
<item quantity="one">"%1$d%% af de samlede stemmer"</item>
<item quantity="other">"%1$d procent af det samlede antal stemmer"</item>
</plurals>
<string name="a11y_polls_will_remove_selection">"Fjerner tidligere valg"</string>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<plurals name="a11y_polls_percent_of_total">
<item quantity="other">"総投票数うち%1$d%%"</item>
</plurals>
<string name="a11y_polls_will_remove_selection">"前の項目を削除します"</string>
<string name="a11y_polls_winning_answer">"投票の勝者はこちらです"</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<plurals name="a11y_polls_percent_of_total">
<item quantity="other">"%1$d phần trăm tổng số phiếu bầu"</item>
</plurals>
<string name="a11y_polls_will_remove_selection">"Xóa lựa chọn trước đó"</string>
<string name="a11y_polls_winning_answer">"Đây là câu trả lời chiến thắng"</string>
</resources>
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<plurals name="a11y_polls_percent_of_total">
<item quantity="other">"%1$d 总投票百分比"</item>
<item quantity="other">"占总投票的 %1$d%"</item>
</plurals>
<string name="a11y_polls_will_remove_selection">"将移除之前的选择"</string>
<string name="a11y_polls_winning_answer">"这是获胜的答案"</string>
<string name="a11y_polls_winning_answer">"此为胜出的答案"</string>
</resources>
@@ -112,7 +112,7 @@ fun CreatePollView(
item {
Column {
ListItem(
headlineContent = {
content = {
TextField(
label = stringResource(id = R.string.screen_create_poll_question_desc),
value = state.question,
@@ -132,7 +132,7 @@ fun CreatePollView(
itemsIndexed(state.answers) { index, answer ->
val isLastItem = index == state.answers.size - 1
ListItem(
headlineContent = {
content = {
TextField(
value = answer.text,
onValueChange = {
@@ -160,7 +160,7 @@ fun CreatePollView(
if (state.canAddAnswer) {
item {
ListItem(
headlineContent = { Text(text = stringResource(id = R.string.screen_create_poll_add_option_btn)) },
content = { Text(text = stringResource(id = R.string.screen_create_poll_add_option_btn)) },
leadingContent = ListItemContent.Icon(
iconSource = IconSource.Vector(CompoundIcons.Plus()),
),
@@ -179,7 +179,7 @@ fun CreatePollView(
Column {
HorizontalDivider()
ListItem(
headlineContent = { Text(text = stringResource(id = R.string.screen_create_poll_max_selections_headline)) },
content = { Text(text = stringResource(id = R.string.screen_create_poll_max_selections_headline)) },
trailingContent = ListItemContent.Custom {
MaxSelectionsStepper(
current = state.maxSelections,
@@ -190,7 +190,7 @@ fun CreatePollView(
},
)
ListItem(
headlineContent = { Text(text = stringResource(id = R.string.screen_create_poll_anonymous_headline)) },
content = { Text(text = stringResource(id = R.string.screen_create_poll_anonymous_headline)) },
supportingContent = { Text(text = stringResource(id = R.string.screen_create_poll_anonymous_desc)) },
trailingContent = ListItemContent.Switch(
checked = state.pollKind == PollKind.Undisclosed,
@@ -205,7 +205,7 @@ fun CreatePollView(
)
if (state.canDelete) {
ListItem(
headlineContent = { Text(text = stringResource(id = CommonStrings.action_delete_poll)) },
content = { Text(text = stringResource(id = CommonStrings.action_delete_poll)) },
style = ListItemStyle.Destructive,
onClick = { state.eventSink(CreatePollEvent.Delete(confirmed = false)) },
)
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_create_poll_add_option_btn">"Afegeix opció"</string>
<string name="screen_create_poll_anonymous_desc">"Mostra els resultats només quan hagi finalitzat la votació"</string>
<string name="screen_create_poll_anonymous_headline">"Amaga vots"</string>
<string name="screen_create_poll_answer_hint">"Opció %1$d"</string>
<string name="screen_create_poll_cancel_confirmation_content_android">"Els canvis no s\'han desat. Segur que vols tornar enrere?"</string>
<string name="screen_create_poll_question_desc">"Pregunta o tema"</string>
<string name="screen_create_poll_question_hint">"De què tracta la votació?"</string>
<string name="screen_create_poll_title">"Crea votació"</string>
<string name="screen_edit_poll_delete_confirmation">"Segur que vols eliminar la votació?"</string>
<string name="screen_edit_poll_delete_confirmation_title">"Elimina votació"</string>
<string name="screen_edit_poll_title">"Edita votació"</string>
<string name="screen_polls_history_empty_ongoing">"No s\'han trobat votacions en curs."</string>
<string name="screen_polls_history_empty_past">"No s\'han trobat votacions passades."</string>
<string name="screen_polls_history_filter_ongoing">"En curs"</string>
<string name="screen_polls_history_filter_past">"Pasades"</string>
<string name="screen_polls_history_title">"Votacions"</string>
</resources>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_create_poll_add_option_btn">"選択肢を追加"</string>
<string name="screen_create_poll_anonymous_desc">"結果を投票終了後に表示します"</string>
<string name="screen_create_poll_anonymous_headline">"投票を非表示"</string>
<string name="screen_create_poll_answer_hint">"選択肢 %1$d"</string>
<string name="screen_create_poll_cancel_confirmation_content_android">"変更は保存されていません。本当に戻りますか?"</string>
<string name="screen_create_poll_delete_option_a11y">"選択肢を削除 %1$s"</string>
<string name="screen_create_poll_question_desc">"質問またはトピック"</string>
<string name="screen_create_poll_question_hint">"何についての投票ですか?"</string>
<string name="screen_create_poll_title">"投票を作成"</string>
<string name="screen_edit_poll_delete_confirmation">"本当にこの投票を削除しますか?"</string>
<string name="screen_edit_poll_delete_confirmation_title">"投票を削除"</string>
<string name="screen_edit_poll_title">"投票を編集"</string>
<string name="screen_polls_history_empty_ongoing">"進行中の投票が見つかりません。"</string>
<string name="screen_polls_history_empty_past">"過去の投票が見つかりません。"</string>
<string name="screen_polls_history_filter_ongoing">"進行中"</string>
<string name="screen_polls_history_filter_past">"過去"</string>
<string name="screen_polls_history_title">"投票"</string>
</resources>
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="screen_create_poll_add_option_btn">"Thêm lựa chọn"</string>
<string name="screen_create_poll_anonymous_desc">"Chỉ hiển thị kết quả sau khi cuộc thăm dò kết thúc"</string>
<string name="screen_create_poll_anonymous_headline">"Ẩn phiếu"</string>
<string name="screen_create_poll_answer_hint">"Lựa chọn %1$d"</string>
<string name="screen_create_poll_cancel_confirmation_content_android">"Các thay đổi của bạn chưa được lưu. Bạn có chắc muốn quay lại không?"</string>
<string name="screen_create_poll_delete_option_a11y">"Tùy chọn xóa %1$s"</string>
<string name="screen_create_poll_question_desc">"Câu hỏi hoặc chủ đề"</string>
<string name="screen_create_poll_question_hint">"Cuộc thăm dò này về vấn đề gì?"</string>
<string name="screen_create_poll_title">"Tạo Cuộc thăm dò ý kiến"</string>
<string name="screen_edit_poll_delete_confirmation">"Bạn có chắc chắn muốn xóa cuộc thăm dò này không?"</string>
<string name="screen_edit_poll_delete_confirmation_title">"Xóa cuộc thăm dò"</string>
<string name="screen_edit_poll_title">"Sửa cuộc thăm dò"</string>
<string name="screen_polls_history_empty_ongoing">"Không tìm thấy bất kỳ cuộc thăm dò nào đang diễn ra."</string>
<string name="screen_polls_history_empty_past">"Không tìm thấy bất kỳ cuộc thăm dò nào trước đây."</string>
<string name="screen_polls_history_filter_ongoing">"Đang diễn ra"</string>
<string name="screen_polls_history_filter_past">"Quá khứ"</string>
<string name="screen_polls_history_title">"Cuộc thăm dò ý kiến"</string>
</resources>
@@ -5,11 +5,11 @@
<string name="screen_create_poll_anonymous_headline">"隐藏投票"</string>
<string name="screen_create_poll_answer_hint">"选项 %1$d"</string>
<string name="screen_create_poll_cancel_confirmation_content_android">"更改尚未保存,确定要返回吗?"</string>
<string name="screen_create_poll_delete_option_a11y">"删除选项%1$s"</string>
<string name="screen_create_poll_delete_option_a11y">"删除选项 %1$s"</string>
<string name="screen_create_poll_question_desc">"问题或话题"</string>
<string name="screen_create_poll_question_hint">"投票的内容是什么?"</string>
<string name="screen_create_poll_title">"创建投票"</string>
<string name="screen_edit_poll_delete_confirmation">"您确定要删除此投票吗?"</string>
<string name="screen_edit_poll_delete_confirmation">"你确定要删除此投票?"</string>
<string name="screen_edit_poll_delete_confirmation_title">"删除投票"</string>
<string name="screen_edit_poll_title">"编辑投票"</string>
<string name="screen_polls_history_empty_ongoing">"无法找到正在进行的投票。"</string>
@@ -6,14 +6,16 @@
* Please see LICENSE files in the repository root for full details.
*/
@file:OptIn(ExperimentalTestApi::class)
package io.element.android.features.poll.impl.history
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.AndroidComposeUiTest
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.compose.ui.test.v2.runAndroidComposeUiTest
import io.element.android.features.poll.api.pollcontent.aPollContentState
import io.element.android.features.poll.impl.R
import io.element.android.features.poll.impl.history.model.PollHistoryFilter
@@ -26,34 +28,28 @@ import io.element.android.tests.testutils.clickOn
import io.element.android.tests.testutils.ensureCalledOnce
import io.element.android.tests.testutils.ensureCalledOnceWithParam
import io.element.android.tests.testutils.pressBack
import org.junit.Rule
import io.element.android.tests.testutils.robolectric.RobolectricTest
import org.junit.Test
import org.junit.rules.TestRule
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
@RunWith(AndroidJUnit4::class)
class PollHistoryViewTest {
@get:Rule
val rule = createAndroidComposeRule<ComponentActivity>()
class PollHistoryViewTest : RobolectricTest() {
@Test
fun `clicking on back invokes the expected callback`() {
fun `clicking on back invokes the expected callback`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<PollHistoryEvents>(expectEvents = false)
ensureCalledOnce {
rule.setPollHistoryViewView(
setPollHistoryViewView(
aPollHistoryState(
eventSink = eventsRecorder
),
goBack = it
)
rule.pressBack()
pressBack()
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `clicking on edit poll invokes the expected callback`() {
fun `clicking on edit poll invokes the expected callback`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<PollHistoryEvents>(expectEvents = false)
val eventId = EventId("\$anEventId")
val state = aPollHistoryState(
@@ -69,17 +65,17 @@ class PollHistoryViewTest {
eventSink = eventsRecorder
)
ensureCalledOnceWithParam(eventId) {
rule.setPollHistoryViewView(
setPollHistoryViewView(
state = state,
onEditPoll = it
)
rule.clickOn(CommonStrings.action_edit_poll)
clickOn(CommonStrings.action_edit_poll)
}
}
@Config(qualifiers = "h1024dp")
@Test
fun `clicking on poll end emits the expected Event`() {
fun `clicking on poll end emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<PollHistoryEvents>()
val eventId = EventId("\$anEventId")
val state = aPollHistoryState(
@@ -95,16 +91,16 @@ class PollHistoryViewTest {
),
eventSink = eventsRecorder
)
rule.setPollHistoryViewView(
setPollHistoryViewView(
state = state,
)
rule.clickOn(CommonStrings.action_end_poll)
clickOn(CommonStrings.action_end_poll)
// Cancel the dialog
rule.clickOn(CommonStrings.action_cancel)
clickOn(CommonStrings.action_cancel)
// Do it again, and confirm the dialog
rule.clickOn(CommonStrings.action_end_poll)
clickOn(CommonStrings.action_end_poll)
eventsRecorder.assertEmpty()
rule.clickOn(CommonStrings.action_ok)
clickOn(CommonStrings.action_ok)
eventsRecorder.assertSingle(
PollHistoryEvents.EndPoll(eventId)
)
@@ -112,7 +108,7 @@ class PollHistoryViewTest {
@Config(qualifiers = "h1024dp")
@Test
fun `clicking on poll answer emits the expected Event`() {
fun `clicking on poll answer emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<PollHistoryEvents>()
val eventId = EventId("\$anEventId")
val state = aPollHistoryState(
@@ -129,10 +125,10 @@ class PollHistoryViewTest {
eventSink = eventsRecorder
)
val answer = state.pollHistoryItems.ongoing.first().state.answerItems.first().answer
rule.setPollHistoryViewView(
setPollHistoryViewView(
state = state,
)
rule.onNodeWithText(
onNodeWithText(
text = answer.text,
useUnmergedTree = true,
).performClick()
@@ -142,14 +138,14 @@ class PollHistoryViewTest {
}
@Test
fun `clicking on past tab emits the expected Event`() {
fun `clicking on past tab emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<PollHistoryEvents>()
rule.setPollHistoryViewView(
setPollHistoryViewView(
aPollHistoryState(
eventSink = eventsRecorder
),
)
rule.clickOn(R.string.screen_polls_history_filter_past)
clickOn(R.string.screen_polls_history_filter_past)
eventsRecorder.assertSingle(
PollHistoryEvents.SelectFilter(filter = PollHistoryFilter.PAST)
)
@@ -157,22 +153,22 @@ class PollHistoryViewTest {
@Config(qualifiers = "h1024dp")
@Test
fun `clicking on load more emits the expected Event`() {
fun `clicking on load more emits the expected Event`() = runAndroidComposeUiTest {
val eventsRecorder = EventsRecorder<PollHistoryEvents>()
rule.setPollHistoryViewView(
setPollHistoryViewView(
aPollHistoryState(
hasMoreToLoad = true,
eventSink = eventsRecorder,
),
)
rule.clickOn(CommonStrings.action_load_more)
clickOn(CommonStrings.action_load_more)
eventsRecorder.assertSingle(
PollHistoryEvents.LoadMore
)
}
}
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setPollHistoryViewView(
private fun AndroidComposeUiTest<ComponentActivity>.setPollHistoryViewView(
state: PollHistoryState,
onEditPoll: (EventId) -> Unit = EnsureNeverCalledWithParam(),
goBack: () -> Unit = EnsureNeverCalled(),
+1
View File
@@ -15,6 +15,7 @@ android {
}
dependencies {
implementation(projects.libraries.architecture)
implementation(projects.libraries.matrix.api)
api(projects.features.poll.api)
implementation(libs.kotlinx.collections.immutable)