mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-05 22:36:34 +00:00
Merge branch 'develop' into renovate/actions-setup-java-5.x
This commit is contained in:
@@ -85,6 +85,7 @@ fun LoggedInView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
LocalNetworkPermissionDialogView(
|
LocalNetworkPermissionDialogView(
|
||||||
|
appName = state.appName,
|
||||||
dialog = state.localNetworkPermissionDialog,
|
dialog = state.localNetworkPermissionDialog,
|
||||||
onSubmit = { state.eventSink(LoggedInEvents.RequestLocationNetworkPermission) },
|
onSubmit = { state.eventSink(LoggedInEvents.RequestLocationNetworkPermission) },
|
||||||
onDismiss = { state.eventSink(LoggedInEvents.DismissLocalNetworkPermissionPrompt) },
|
onDismiss = { state.eventSink(LoggedInEvents.DismissLocalNetworkPermissionPrompt) },
|
||||||
|
|||||||
+4
-4
@@ -88,7 +88,7 @@ class DefaultInvitePeoplePresenter(
|
|||||||
override fun present(): InvitePeopleState {
|
override fun present(): InvitePeopleState {
|
||||||
val roomMembers = remember { mutableStateOf<AsyncData<ImmutableList<RoomMember>>>(AsyncData.Loading()) }
|
val roomMembers = remember { mutableStateOf<AsyncData<ImmutableList<RoomMember>>>(AsyncData.Loading()) }
|
||||||
val selectedUsers = remember { mutableStateOf<ImmutableList<MatrixUser>>(persistentListOf()) }
|
val selectedUsers = remember { mutableStateOf<ImmutableList<MatrixUser>>(persistentListOf()) }
|
||||||
val searchResults = remember { mutableStateOf<SearchBarResultState<ImmutableList<InvitableUser>>>(SearchBarResultState.Initial()) }
|
val searchResults = remember { mutableStateOf<SearchBarResultState<ImmutableList<InvitableUser>>>(SearchBarResultState.Initial) }
|
||||||
val queryState = rememberTextFieldState()
|
val queryState = rememberTextFieldState()
|
||||||
var searchActive by rememberSaveable { mutableStateOf(false) }
|
var searchActive by rememberSaveable { mutableStateOf(false) }
|
||||||
val showSearchLoader = rememberSaveable { mutableStateOf(false) }
|
val showSearchLoader = rememberSaveable { mutableStateOf(false) }
|
||||||
@@ -332,15 +332,15 @@ class DefaultInvitePeoplePresenter(
|
|||||||
showSearchLoader: MutableState<Boolean>,
|
showSearchLoader: MutableState<Boolean>,
|
||||||
searchQuery: String,
|
searchQuery: String,
|
||||||
) = withContext(coroutineDispatchers.io) {
|
) = withContext(coroutineDispatchers.io) {
|
||||||
searchResults.value = SearchBarResultState.Initial()
|
searchResults.value = SearchBarResultState.Initial
|
||||||
showSearchLoader.value = false
|
showSearchLoader.value = false
|
||||||
val joinedMembers = roomMembers.value.dataOrNull().orEmpty()
|
val joinedMembers = roomMembers.value.dataOrNull().orEmpty()
|
||||||
|
|
||||||
userRepository.search(searchQuery).onEach { state ->
|
userRepository.search(searchQuery).onEach { state ->
|
||||||
showSearchLoader.value = state.isSearching
|
showSearchLoader.value = state.isSearching
|
||||||
searchResults.value = when {
|
searchResults.value = when {
|
||||||
state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial()
|
state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial
|
||||||
state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound()
|
state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound
|
||||||
else -> SearchBarResultState.Results(state.results.map { result ->
|
else -> SearchBarResultState.Results(state.results.map { result ->
|
||||||
val existingMembership = joinedMembers.firstOrNull { j -> j.userId == result.matrixUser.userId }?.membership
|
val existingMembership = joinedMembers.firstOrNull { j -> j.userId == result.matrixUser.userId }?.membership
|
||||||
val isJoined = existingMembership == RoomMembershipState.JOIN
|
val isJoined = existingMembership == RoomMembershipState.JOIN
|
||||||
|
|||||||
+2
-2
@@ -33,7 +33,7 @@ internal class DefaultInvitePeopleStateProvider : PreviewParameterProvider<Defau
|
|||||||
aDefaultInvitePeopleState(canInvite = true, selectedUsers = aMatrixUserList().toImmutableList()),
|
aDefaultInvitePeopleState(canInvite = true, selectedUsers = aMatrixUserList().toImmutableList()),
|
||||||
aDefaultInvitePeopleState(isSearchActive = true, searchQuery = "some query"),
|
aDefaultInvitePeopleState(isSearchActive = true, searchQuery = "some query"),
|
||||||
aDefaultInvitePeopleState(isSearchActive = true, searchQuery = "some query", selectedUsers = aMatrixUserList().toImmutableList()),
|
aDefaultInvitePeopleState(isSearchActive = true, searchQuery = "some query", selectedUsers = aMatrixUserList().toImmutableList()),
|
||||||
aDefaultInvitePeopleState(isSearchActive = true, searchQuery = "some query", searchResults = SearchBarResultState.NoResultsFound()),
|
aDefaultInvitePeopleState(isSearchActive = true, searchQuery = "some query", searchResults = SearchBarResultState.NoResultsFound),
|
||||||
aDefaultInvitePeopleState(
|
aDefaultInvitePeopleState(
|
||||||
isSearchActive = true,
|
isSearchActive = true,
|
||||||
canInvite = true,
|
canInvite = true,
|
||||||
@@ -115,7 +115,7 @@ private fun aDefaultInvitePeopleState(
|
|||||||
room: AsyncData<Unit> = AsyncData.Success(Unit),
|
room: AsyncData<Unit> = AsyncData.Success(Unit),
|
||||||
canInvite: Boolean = false,
|
canInvite: Boolean = false,
|
||||||
searchQuery: String = "",
|
searchQuery: String = "",
|
||||||
searchResults: SearchBarResultState<ImmutableList<InvitableUser>> = SearchBarResultState.Initial(),
|
searchResults: SearchBarResultState<ImmutableList<InvitableUser>> = SearchBarResultState.Initial,
|
||||||
selectedUsers: ImmutableList<MatrixUser> = persistentListOf(),
|
selectedUsers: ImmutableList<MatrixUser> = persistentListOf(),
|
||||||
isSearchActive: Boolean = false,
|
isSearchActive: Boolean = false,
|
||||||
showSearchLoader: Boolean = false,
|
showSearchLoader: Boolean = false,
|
||||||
|
|||||||
+4
-8
@@ -95,7 +95,7 @@ internal class DefaultInvitePeoplePresenterTest {
|
|||||||
resultState.searchQuery.setTextAndPlaceCursorAtEnd("some query")
|
resultState.searchQuery.setTextAndPlaceCursorAtEnd("some query")
|
||||||
assertThat(awaitItemAsDefault().searchQuery.text.toString()).isEqualTo("some query")
|
assertThat(awaitItemAsDefault().searchQuery.text.toString()).isEqualTo("some query")
|
||||||
resultState.eventSink(InvitePeopleEvents.CloseSearch)
|
resultState.eventSink(InvitePeopleEvents.CloseSearch)
|
||||||
skipItems(2)
|
skipItems(1)
|
||||||
awaitItemAsDefault().also {
|
awaitItemAsDefault().also {
|
||||||
assertThat(it.isSearchActive).isFalse()
|
assertThat(it.isSearchActive).isFalse()
|
||||||
assertThat(it.searchQuery.text.toString()).isEmpty()
|
assertThat(it.searchQuery.text.toString()).isEmpty()
|
||||||
@@ -116,7 +116,7 @@ internal class DefaultInvitePeoplePresenterTest {
|
|||||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd("some query")
|
initialState.searchQuery.setTextAndPlaceCursorAtEnd("some query")
|
||||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||||
repository.emitState(UserSearchResultState(results = emptyList(), isSearching = true))
|
repository.emitState(UserSearchResultState(results = emptyList(), isSearching = true))
|
||||||
skipItems(3)
|
skipItems(2)
|
||||||
awaitItemAsDefault().also { state ->
|
awaitItemAsDefault().also { state ->
|
||||||
assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
|
assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
|
||||||
assertThat(state.showSearchLoader).isTrue()
|
assertThat(state.showSearchLoader).isTrue()
|
||||||
@@ -145,7 +145,6 @@ internal class DefaultInvitePeoplePresenterTest {
|
|||||||
|
|
||||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||||
repository.emitStateWithUsers(users = aMatrixUserList())
|
repository.emitStateWithUsers(users = aMatrixUserList())
|
||||||
skipItems(1)
|
|
||||||
|
|
||||||
val resultState = awaitItemAsDefault()
|
val resultState = awaitItemAsDefault()
|
||||||
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
||||||
@@ -198,7 +197,6 @@ internal class DefaultInvitePeoplePresenterTest {
|
|||||||
|
|
||||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||||
repository.emitStateWithUsers(users = aMatrixUserList())
|
repository.emitStateWithUsers(users = aMatrixUserList())
|
||||||
skipItems(1)
|
|
||||||
|
|
||||||
val resultState = awaitItemAsDefault()
|
val resultState = awaitItemAsDefault()
|
||||||
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
||||||
@@ -265,7 +263,6 @@ internal class DefaultInvitePeoplePresenterTest {
|
|||||||
it
|
it
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
skipItems(1)
|
|
||||||
|
|
||||||
val resultState = awaitItemAsDefault()
|
val resultState = awaitItemAsDefault()
|
||||||
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
||||||
@@ -329,7 +326,7 @@ internal class DefaultInvitePeoplePresenterTest {
|
|||||||
|
|
||||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||||
repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser)
|
repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser)
|
||||||
skipItems(2)
|
skipItems(1)
|
||||||
|
|
||||||
val resultState = awaitItemAsDefault()
|
val resultState = awaitItemAsDefault()
|
||||||
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
||||||
@@ -366,7 +363,6 @@ internal class DefaultInvitePeoplePresenterTest {
|
|||||||
|
|
||||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||||
repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser)
|
repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser)
|
||||||
skipItems(1)
|
|
||||||
awaitItemAsDefault().also { state ->
|
awaitItemAsDefault().also { state ->
|
||||||
// selectedUser is not selected
|
// selectedUser is not selected
|
||||||
assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
||||||
@@ -732,7 +728,7 @@ internal class DefaultInvitePeoplePresenterTest {
|
|||||||
isSearching = true
|
isSearching = true
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
skipItems(3)
|
skipItems(2)
|
||||||
|
|
||||||
awaitItemAsDefault().run {
|
awaitItemAsDefault().run {
|
||||||
assertThat(selectedUsers).containsExactly(alice, bob, charlie)
|
assertThat(selectedUsers).containsExactly(alice, bob, charlie)
|
||||||
|
|||||||
+1
@@ -123,6 +123,7 @@ fun ChangeServerView(
|
|||||||
AsyncData.Uninitialized -> Unit
|
AsyncData.Uninitialized -> Unit
|
||||||
}
|
}
|
||||||
LocalNetworkPermissionDialogView(
|
LocalNetworkPermissionDialogView(
|
||||||
|
appName = LocalBuildMeta.current.applicationName,
|
||||||
dialog = state.localNetworkPermissionDialog,
|
dialog = state.localNetworkPermissionDialog,
|
||||||
onSubmit = {
|
onSubmit = {
|
||||||
eventSink.invoke(ChangeServerEvents.RequestLocalNetworkPermission)
|
eventSink.invoke(ChangeServerEvents.RequestLocalNetworkPermission)
|
||||||
|
|||||||
+2
@@ -41,6 +41,7 @@ import io.element.android.libraries.designsystem.components.BigIcon
|
|||||||
import io.element.android.libraries.designsystem.components.button.BackButton
|
import io.element.android.libraries.designsystem.components.button.BackButton
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
|
import io.element.android.libraries.designsystem.theme.LocalBuildMeta
|
||||||
import io.element.android.libraries.designsystem.theme.components.Button
|
import io.element.android.libraries.designsystem.theme.components.Button
|
||||||
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
import io.element.android.libraries.designsystem.theme.components.Scaffold
|
||||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||||
@@ -138,6 +139,7 @@ fun ChooseAccountProviderView(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
LocalNetworkPermissionDialogView(
|
LocalNetworkPermissionDialogView(
|
||||||
|
appName = LocalBuildMeta.current.applicationName,
|
||||||
dialog = state.loginModeState.localNetworkPermissionDialog,
|
dialog = state.loginModeState.localNetworkPermissionDialog,
|
||||||
onSubmit = {
|
onSubmit = {
|
||||||
state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission)
|
state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission)
|
||||||
|
|||||||
+2
@@ -47,6 +47,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
|||||||
import io.element.android.libraries.designsystem.components.avatar.BitmapAvatar
|
import io.element.android.libraries.designsystem.components.avatar.BitmapAvatar
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
|
import io.element.android.libraries.designsystem.theme.LocalBuildMeta
|
||||||
import io.element.android.libraries.designsystem.theme.components.Button
|
import io.element.android.libraries.designsystem.theme.components.Button
|
||||||
import io.element.android.libraries.designsystem.theme.components.OutlinedButton
|
import io.element.android.libraries.designsystem.theme.components.OutlinedButton
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
@@ -207,6 +208,7 @@ fun LoginWithClassicView(
|
|||||||
onCreateAccountContinue = onCreateAccountContinue,
|
onCreateAccountContinue = onCreateAccountContinue,
|
||||||
)
|
)
|
||||||
LocalNetworkPermissionDialogView(
|
LocalNetworkPermissionDialogView(
|
||||||
|
appName = LocalBuildMeta.current.applicationName,
|
||||||
dialog = state.loginModeState.localNetworkPermissionDialog,
|
dialog = state.loginModeState.localNetworkPermissionDialog,
|
||||||
onSubmit = {
|
onSubmit = {
|
||||||
state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission)
|
state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission)
|
||||||
|
|||||||
+2
@@ -29,6 +29,7 @@ import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
|
|||||||
import io.element.android.libraries.designsystem.components.BigIcon
|
import io.element.android.libraries.designsystem.components.BigIcon
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreview
|
import io.element.android.libraries.designsystem.preview.ElementPreview
|
||||||
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
|
||||||
|
import io.element.android.libraries.designsystem.theme.LocalBuildMeta
|
||||||
import io.element.android.libraries.designsystem.theme.components.Button
|
import io.element.android.libraries.designsystem.theme.components.Button
|
||||||
import io.element.android.libraries.designsystem.theme.components.TextButton
|
import io.element.android.libraries.designsystem.theme.components.TextButton
|
||||||
import io.element.android.libraries.matrix.api.auth.OAuthDetails
|
import io.element.android.libraries.matrix.api.auth.OAuthDetails
|
||||||
@@ -112,6 +113,7 @@ fun ConfirmAccountProviderView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
LocalNetworkPermissionDialogView(
|
LocalNetworkPermissionDialogView(
|
||||||
|
appName = LocalBuildMeta.current.applicationName,
|
||||||
dialog = state.loginModeState.localNetworkPermissionDialog,
|
dialog = state.loginModeState.localNetworkPermissionDialog,
|
||||||
onSubmit = {
|
onSubmit = {
|
||||||
state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission)
|
state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission)
|
||||||
|
|||||||
+1
@@ -87,6 +87,7 @@ fun OnBoardingView(
|
|||||||
onCreateAccountContinue = onCreateAccountContinue,
|
onCreateAccountContinue = onCreateAccountContinue,
|
||||||
)
|
)
|
||||||
LocalNetworkPermissionDialogView(
|
LocalNetworkPermissionDialogView(
|
||||||
|
appName = state.productionApplicationName,
|
||||||
dialog = state.loginModeState.localNetworkPermissionDialog,
|
dialog = state.loginModeState.localNetworkPermissionDialog,
|
||||||
onSubmit = {
|
onSubmit = {
|
||||||
state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission)
|
state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission)
|
||||||
|
|||||||
+2
-2
@@ -77,7 +77,7 @@ class ChangeRolesPresenter(
|
|||||||
val queryState = rememberTextFieldState()
|
val queryState = rememberTextFieldState()
|
||||||
var searchActive by rememberSaveable { mutableStateOf(false) }
|
var searchActive by rememberSaveable { mutableStateOf(false) }
|
||||||
var searchResults by remember {
|
var searchResults by remember {
|
||||||
mutableStateOf<SearchBarResultState<MembersByRole>>(SearchBarResultState.Initial())
|
mutableStateOf<SearchBarResultState<MembersByRole>>(SearchBarResultState.Initial)
|
||||||
}
|
}
|
||||||
val selectedUsers = remember {
|
val selectedUsers = remember {
|
||||||
mutableStateOf<ImmutableList<MatrixUser>>(persistentListOf())
|
mutableStateOf<ImmutableList<MatrixUser>>(persistentListOf())
|
||||||
@@ -118,7 +118,7 @@ class ChangeRolesPresenter(
|
|||||||
.groupedByRole()
|
.groupedByRole()
|
||||||
|
|
||||||
searchResults = if (results.isEmpty()) {
|
searchResults = if (results.isEmpty()) {
|
||||||
SearchBarResultState.NoResultsFound()
|
SearchBarResultState.NoResultsFound
|
||||||
} else {
|
} else {
|
||||||
SearchBarResultState.Results(results)
|
SearchBarResultState.Results(results)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -68,7 +68,7 @@ internal fun aChangeRolesState(
|
|||||||
role: RoomMember.Role = RoomMember.Role.Admin,
|
role: RoomMember.Role = RoomMember.Role.Admin,
|
||||||
searchQuery: String = "",
|
searchQuery: String = "",
|
||||||
isSearchActive: Boolean = false,
|
isSearchActive: Boolean = false,
|
||||||
searchResults: SearchBarResultState<MembersByRole> = SearchBarResultState.NoResultsFound(),
|
searchResults: SearchBarResultState<MembersByRole> = SearchBarResultState.NoResultsFound,
|
||||||
selectedUsers: ImmutableList<MatrixUser> = persistentListOf(),
|
selectedUsers: ImmutableList<MatrixUser> = persistentListOf(),
|
||||||
hasPendingChanges: Boolean = false,
|
hasPendingChanges: Boolean = false,
|
||||||
savingState: AsyncAction<Boolean> = AsyncAction.Uninitialized,
|
savingState: AsyncAction<Boolean> = AsyncAction.Uninitialized,
|
||||||
|
|||||||
+2
-2
@@ -66,8 +66,8 @@ class AddRoomToSpacePresenter(
|
|||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
when {
|
when {
|
||||||
filteredRooms.isNotEmpty() -> SearchBarResultState.Results(filteredRooms)
|
filteredRooms.isNotEmpty() -> SearchBarResultState.Results(filteredRooms)
|
||||||
isSearchActive && searchQuery.text.isNotEmpty() -> SearchBarResultState.NoResultsFound<ImmutableList<SelectRoomInfo>>()
|
isSearchActive && searchQuery.text.isNotEmpty() -> SearchBarResultState.NoResultsFound
|
||||||
else -> SearchBarResultState.Initial<ImmutableList<SelectRoomInfo>>()
|
else -> SearchBarResultState.Initial
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -40,7 +40,7 @@ internal class AddRoomToSpaceStateProvider : PreviewParameterProvider<AddRoomToS
|
|||||||
anAddRoomToSpaceState(
|
anAddRoomToSpaceState(
|
||||||
isSearchActive = true,
|
isSearchActive = true,
|
||||||
searchQuery = "unknown",
|
searchQuery = "unknown",
|
||||||
searchResults = SearchBarResultState.NoResultsFound(),
|
searchResults = SearchBarResultState.NoResultsFound,
|
||||||
),
|
),
|
||||||
// With selected rooms
|
// With selected rooms
|
||||||
anAddRoomToSpaceState(
|
anAddRoomToSpaceState(
|
||||||
@@ -62,7 +62,7 @@ internal class AddRoomToSpaceStateProvider : PreviewParameterProvider<AddRoomToS
|
|||||||
|
|
||||||
internal fun anAddRoomToSpaceState(
|
internal fun anAddRoomToSpaceState(
|
||||||
searchQuery: String = "",
|
searchQuery: String = "",
|
||||||
searchResults: SearchBarResultState<ImmutableList<SelectRoomInfo>> = SearchBarResultState.Initial(),
|
searchResults: SearchBarResultState<ImmutableList<SelectRoomInfo>> = SearchBarResultState.Initial,
|
||||||
selectedRooms: ImmutableList<SelectRoomInfo> = persistentListOf(),
|
selectedRooms: ImmutableList<SelectRoomInfo> = persistentListOf(),
|
||||||
isSearchActive: Boolean = false,
|
isSearchActive: Boolean = false,
|
||||||
saveAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
saveAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
||||||
|
|||||||
+4
-4
@@ -67,19 +67,19 @@ class DefaultUserListPresenter(
|
|||||||
val selectedUsers by userListDataStore.selectedUsers.collectAsState(emptyList())
|
val selectedUsers by userListDataStore.selectedUsers.collectAsState(emptyList())
|
||||||
val queryState = rememberTextFieldState()
|
val queryState = rememberTextFieldState()
|
||||||
var searchResults: SearchBarResultState<ImmutableList<UserSearchResult>> by remember {
|
var searchResults: SearchBarResultState<ImmutableList<UserSearchResult>> by remember {
|
||||||
mutableStateOf(SearchBarResultState.Initial())
|
mutableStateOf(SearchBarResultState.Initial)
|
||||||
}
|
}
|
||||||
var showSearchLoader by remember { mutableStateOf(false) }
|
var showSearchLoader by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
val searchQuery = queryState.text.toString()
|
val searchQuery = queryState.text.toString()
|
||||||
LaunchedEffect(searchQuery) {
|
LaunchedEffect(searchQuery) {
|
||||||
searchResults = SearchBarResultState.Initial()
|
searchResults = SearchBarResultState.Initial
|
||||||
showSearchLoader = false
|
showSearchLoader = false
|
||||||
userRepository.search(searchQuery).onEach { state ->
|
userRepository.search(searchQuery).onEach { state ->
|
||||||
showSearchLoader = state.isSearching
|
showSearchLoader = state.isSearching
|
||||||
searchResults = when {
|
searchResults = when {
|
||||||
state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial()
|
state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial
|
||||||
state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound()
|
state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound
|
||||||
else -> SearchBarResultState.Results(state.results.toImmutableList())
|
else -> SearchBarResultState.Results(state.results.toImmutableList())
|
||||||
}
|
}
|
||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
|
|||||||
+2
-2
@@ -47,7 +47,7 @@ open class UserListStateProvider : PreviewParameterProvider<UserListState> {
|
|||||||
aUserListState(
|
aUserListState(
|
||||||
isSearchActive = true,
|
isSearchActive = true,
|
||||||
searchQuery = "something-with-no-results",
|
searchQuery = "something-with-no-results",
|
||||||
searchResults = SearchBarResultState.NoResultsFound()
|
searchResults = SearchBarResultState.NoResultsFound
|
||||||
),
|
),
|
||||||
aUserListState(
|
aUserListState(
|
||||||
isSearchActive = true,
|
isSearchActive = true,
|
||||||
@@ -63,7 +63,7 @@ open class UserListStateProvider : PreviewParameterProvider<UserListState> {
|
|||||||
fun aUserListState(
|
fun aUserListState(
|
||||||
searchQuery: String = "",
|
searchQuery: String = "",
|
||||||
isSearchActive: Boolean = false,
|
isSearchActive: Boolean = false,
|
||||||
searchResults: SearchBarResultState<ImmutableList<UserSearchResult>> = SearchBarResultState.Initial(),
|
searchResults: SearchBarResultState<ImmutableList<UserSearchResult>> = SearchBarResultState.Initial,
|
||||||
selectedUsers: List<MatrixUser> = emptyList(),
|
selectedUsers: List<MatrixUser> = emptyList(),
|
||||||
showSearchLoader: Boolean = false,
|
showSearchLoader: Boolean = false,
|
||||||
selectionMode: SelectionMode = SelectionMode.Single,
|
selectionMode: SelectionMode = SelectionMode.Single,
|
||||||
|
|||||||
+2
-10
@@ -40,7 +40,6 @@ class DefaultUserListPresenterTest {
|
|||||||
FakeMatrixClient(),
|
FakeMatrixClient(),
|
||||||
)
|
)
|
||||||
presenter.test {
|
presenter.test {
|
||||||
skipItems(1)
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
assertThat(initialState.searchQuery.text.toString()).isEmpty()
|
assertThat(initialState.searchQuery.text.toString()).isEmpty()
|
||||||
assertThat(initialState.isMultiSelectionEnabled).isFalse()
|
assertThat(initialState.isMultiSelectionEnabled).isFalse()
|
||||||
@@ -60,7 +59,6 @@ class DefaultUserListPresenterTest {
|
|||||||
FakeMatrixClient(),
|
FakeMatrixClient(),
|
||||||
)
|
)
|
||||||
presenter.test {
|
presenter.test {
|
||||||
skipItems(1)
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
assertThat(initialState.searchQuery.text.toString()).isEmpty()
|
assertThat(initialState.searchQuery.text.toString()).isEmpty()
|
||||||
assertThat(initialState.isMultiSelectionEnabled).isTrue()
|
assertThat(initialState.isMultiSelectionEnabled).isTrue()
|
||||||
@@ -80,7 +78,6 @@ class DefaultUserListPresenterTest {
|
|||||||
FakeMatrixClient(),
|
FakeMatrixClient(),
|
||||||
)
|
)
|
||||||
presenter.test {
|
presenter.test {
|
||||||
skipItems(1)
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
|
|
||||||
initialState.eventSink(UserListEvents.OnSearchActiveChanged(true))
|
initialState.eventSink(UserListEvents.OnSearchActiveChanged(true))
|
||||||
@@ -90,13 +87,11 @@ class DefaultUserListPresenterTest {
|
|||||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd(matrixIdQuery)
|
initialState.searchQuery.setTextAndPlaceCursorAtEnd(matrixIdQuery)
|
||||||
assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(matrixIdQuery)
|
assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(matrixIdQuery)
|
||||||
assertThat(userRepository.providedQuery).isEqualTo(matrixIdQuery)
|
assertThat(userRepository.providedQuery).isEqualTo(matrixIdQuery)
|
||||||
skipItems(1)
|
|
||||||
|
|
||||||
val notMatrixIdQuery = "name"
|
val notMatrixIdQuery = "name"
|
||||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd(notMatrixIdQuery)
|
initialState.searchQuery.setTextAndPlaceCursorAtEnd(notMatrixIdQuery)
|
||||||
assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(notMatrixIdQuery)
|
assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(notMatrixIdQuery)
|
||||||
assertThat(userRepository.providedQuery).isEqualTo(notMatrixIdQuery)
|
assertThat(userRepository.providedQuery).isEqualTo(notMatrixIdQuery)
|
||||||
skipItems(1)
|
|
||||||
|
|
||||||
initialState.eventSink(UserListEvents.OnSearchActiveChanged(false))
|
initialState.eventSink(UserListEvents.OnSearchActiveChanged(false))
|
||||||
assertThat(awaitItem().isSearchActive).isFalse()
|
assertThat(awaitItem().isSearchActive).isFalse()
|
||||||
@@ -115,13 +110,12 @@ class DefaultUserListPresenterTest {
|
|||||||
FakeMatrixClient(),
|
FakeMatrixClient(),
|
||||||
)
|
)
|
||||||
presenter.test {
|
presenter.test {
|
||||||
skipItems(1)
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
|
|
||||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice")
|
initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice")
|
||||||
assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
|
assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
|
||||||
assertThat(userRepository.providedQuery).isEqualTo("alice")
|
assertThat(userRepository.providedQuery).isEqualTo("alice")
|
||||||
skipItems(2)
|
skipItems(1)
|
||||||
|
|
||||||
// When the user repository emits a result, it's copied to the state
|
// When the user repository emits a result, it's copied to the state
|
||||||
val result = UserSearchResultState(
|
val result = UserSearchResultState(
|
||||||
@@ -166,13 +160,12 @@ class DefaultUserListPresenterTest {
|
|||||||
FakeMatrixClient(),
|
FakeMatrixClient(),
|
||||||
)
|
)
|
||||||
presenter.test {
|
presenter.test {
|
||||||
skipItems(1)
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
|
|
||||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice")
|
initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice")
|
||||||
assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
|
assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
|
||||||
assertThat(userRepository.providedQuery).isEqualTo("alice")
|
assertThat(userRepository.providedQuery).isEqualTo("alice")
|
||||||
skipItems(2)
|
skipItems(1)
|
||||||
|
|
||||||
// When the results list is empty, the state is set to NoResults
|
// When the results list is empty, the state is set to NoResults
|
||||||
userRepository.emitState(UserSearchResultState(results = emptyList(), isSearching = false))
|
userRepository.emitState(UserSearchResultState(results = emptyList(), isSearching = false))
|
||||||
@@ -190,7 +183,6 @@ class DefaultUserListPresenterTest {
|
|||||||
FakeMatrixClient(),
|
FakeMatrixClient(),
|
||||||
)
|
)
|
||||||
presenter.test {
|
presenter.test {
|
||||||
skipItems(1)
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
|
|
||||||
val userA = aMatrixUser("@userA:domain", "A")
|
val userA = aMatrixUser("@userA:domain", "A")
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ telephoto = "0.19.0"
|
|||||||
haze = "1.7.2"
|
haze = "1.7.2"
|
||||||
|
|
||||||
# Dependency analysis
|
# Dependency analysis
|
||||||
dependencyAnalysis = "3.16.1"
|
dependencyAnalysis = "3.17.0"
|
||||||
|
|
||||||
# DI
|
# DI
|
||||||
metro = "1.3.2"
|
metro = "1.3.2"
|
||||||
|
|||||||
+7
-7
@@ -59,7 +59,7 @@ fun <T> SearchBar(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
enabled: Boolean = true,
|
enabled: Boolean = true,
|
||||||
showBackButton: Boolean = true,
|
showBackButton: Boolean = true,
|
||||||
resultState: SearchBarResultState<T> = SearchBarResultState.Initial(),
|
resultState: SearchBarResultState<T> = SearchBarResultState.Initial,
|
||||||
shape: Shape = SearchBarDefaults.inputFieldShape,
|
shape: Shape = SearchBarDefaults.inputFieldShape,
|
||||||
tonalElevation: Dp = SearchBarDefaults.TonalElevation,
|
tonalElevation: Dp = SearchBarDefaults.TonalElevation,
|
||||||
windowInsets: WindowInsets = SearchBarDefaults.windowInsets,
|
windowInsets: WindowInsets = SearchBarDefaults.windowInsets,
|
||||||
@@ -134,7 +134,7 @@ fun <T> SearchBar(
|
|||||||
resultHandler(resultState.results)
|
resultHandler(resultState.results)
|
||||||
}
|
}
|
||||||
|
|
||||||
is SearchBarResultState.NoResultsFound<T> -> {
|
is SearchBarResultState.NoResultsFound -> {
|
||||||
// No results found, show a message
|
// No results found, show a message
|
||||||
Spacer(Modifier.size(80.dp))
|
Spacer(Modifier.size(80.dp))
|
||||||
|
|
||||||
@@ -200,12 +200,12 @@ object ElementSearchBarDefaults {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
sealed interface SearchBarResultState<in T> {
|
sealed interface SearchBarResultState<out T> {
|
||||||
/** No search results are available yet (e.g. because the user hasn't entered a search term). */
|
/** No search results are available yet (e.g. because the user hasn't entered a search term). */
|
||||||
class Initial<T> : SearchBarResultState<T>
|
data object Initial : SearchBarResultState<Nothing>
|
||||||
|
|
||||||
/** The search has completed, but no results were found. */
|
/** The search has completed, but no results were found. */
|
||||||
class NoResultsFound<T> : SearchBarResultState<T>
|
data object NoResultsFound : SearchBarResultState<Nothing>
|
||||||
|
|
||||||
/** The search has completed, and some matching users were found. */
|
/** The search has completed, and some matching users were found. */
|
||||||
data class Results<T>(val results: T) : SearchBarResultState<T>
|
data class Results<T>(val results: T) : SearchBarResultState<T>
|
||||||
@@ -249,7 +249,7 @@ internal fun SearchBarActiveWithNoResultsPreview() = ElementThemedPreview {
|
|||||||
ContentToPreview(
|
ContentToPreview(
|
||||||
initialQuery = "search term",
|
initialQuery = "search term",
|
||||||
active = true,
|
active = true,
|
||||||
resultState = SearchBarResultState.NoResultsFound<String>(),
|
resultState = SearchBarResultState.NoResultsFound,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,7 +293,7 @@ private fun ContentToPreview(
|
|||||||
initialQuery: String = "",
|
initialQuery: String = "",
|
||||||
active: Boolean = false,
|
active: Boolean = false,
|
||||||
showBackButton: Boolean = true,
|
showBackButton: Boolean = true,
|
||||||
resultState: SearchBarResultState<String> = SearchBarResultState.Initial(),
|
resultState: SearchBarResultState<String> = SearchBarResultState.Initial,
|
||||||
contentPrefix: @Composable ColumnScope.() -> Unit = {},
|
contentPrefix: @Composable ColumnScope.() -> Unit = {},
|
||||||
contentSuffix: @Composable ColumnScope.() -> Unit = {},
|
contentSuffix: @Composable ColumnScope.() -> Unit = {},
|
||||||
resultHandler: @Composable ColumnScope.(String) -> Unit = {},
|
resultHandler: @Composable ColumnScope.(String) -> Unit = {},
|
||||||
|
|||||||
+2
-6
@@ -55,7 +55,7 @@ class DefaultEmojiPickerPresenter(
|
|||||||
override fun present(): EmojiPickerState {
|
override fun present(): EmojiPickerState {
|
||||||
val queryState = rememberTextFieldState()
|
val queryState = rememberTextFieldState()
|
||||||
var isSearchActive by remember { mutableStateOf(false) }
|
var isSearchActive by remember { mutableStateOf(false) }
|
||||||
var emojiResults by remember { mutableStateOf<SearchBarResultState<ImmutableList<Emoji>>>(SearchBarResultState.Initial()) }
|
var emojiResults by remember { mutableStateOf<SearchBarResultState<ImmutableList<Emoji>>>(SearchBarResultState.Initial) }
|
||||||
|
|
||||||
val data by produceState(EmojiPickerData.Empty) {
|
val data by produceState(EmojiPickerData.Empty) {
|
||||||
val storeDeferred = async { emojibaseProvider.getStore() }
|
val storeDeferred = async { emojibaseProvider.getStore() }
|
||||||
@@ -93,11 +93,7 @@ class DefaultEmojiPickerPresenter(
|
|||||||
val searchQuery = queryState.text.toString()
|
val searchQuery = queryState.text.toString()
|
||||||
LaunchedEffect(searchQuery, data) {
|
LaunchedEffect(searchQuery, data) {
|
||||||
if (searchQuery.isEmpty() || data.allEmojis.isEmpty()) {
|
if (searchQuery.isEmpty() || data.allEmojis.isEmpty()) {
|
||||||
// `SearchBarResultState.Initial` has no `equals` override, so reassigning a new instance
|
emojiResults = SearchBarResultState.Initial
|
||||||
// would trigger a redundant emission each time this effect re-runs while the query is empty.
|
|
||||||
if (emojiResults !is SearchBarResultState.Initial) {
|
|
||||||
emojiResults = SearchBarResultState.Initial()
|
|
||||||
}
|
|
||||||
return@LaunchedEffect
|
return@LaunchedEffect
|
||||||
}
|
}
|
||||||
delay(100.milliseconds)
|
delay(100.milliseconds)
|
||||||
|
|||||||
+1
-1
@@ -62,7 +62,7 @@ internal fun aDefaultEmojiPickerState(
|
|||||||
}.toImmutableList(),
|
}.toImmutableList(),
|
||||||
searchQuery: String = "",
|
searchQuery: String = "",
|
||||||
isSearchActive: Boolean = false,
|
isSearchActive: Boolean = false,
|
||||||
searchResults: SearchBarResultState<ImmutableList<Emoji>> = SearchBarResultState.Initial(),
|
searchResults: SearchBarResultState<ImmutableList<Emoji>> = SearchBarResultState.Initial,
|
||||||
eventSink: (EmojiPickerEvent) -> Unit = {},
|
eventSink: (EmojiPickerEvent) -> Unit = {},
|
||||||
) = DefaultEmojiPickerState(
|
) = DefaultEmojiPickerState(
|
||||||
categories = categories,
|
categories = categories,
|
||||||
|
|||||||
+2
-1
@@ -15,6 +15,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LocalNetworkPermissionDialogView(
|
fun LocalNetworkPermissionDialogView(
|
||||||
|
appName: String,
|
||||||
dialog: LocalNetworkPermissionDialog,
|
dialog: LocalNetworkPermissionDialog,
|
||||||
onSubmit: () -> Unit,
|
onSubmit: () -> Unit,
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
@@ -27,7 +28,7 @@ fun LocalNetworkPermissionDialogView(
|
|||||||
}
|
}
|
||||||
ConfirmationDialog(
|
ConfirmationDialog(
|
||||||
title = stringResource(CommonStrings.screen_local_network_opt_in_title),
|
title = stringResource(CommonStrings.screen_local_network_opt_in_title),
|
||||||
content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle),
|
content = stringResource(CommonStrings.screen_local_network_opt_in_subtitle, appName),
|
||||||
submitText = stringResource(submitTextRes),
|
submitText = stringResource(submitTextRes),
|
||||||
cancelText = stringResource(CommonStrings.action_not_now),
|
cancelText = stringResource(CommonStrings.action_not_now),
|
||||||
onSubmitClick = onSubmit,
|
onSubmitClick = onSubmit,
|
||||||
|
|||||||
+2
-2
@@ -65,8 +65,8 @@ class RoomSelectPresenter(
|
|||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
when {
|
when {
|
||||||
roomSummaryDetailsList.isNotEmpty() -> SearchBarResultState.Results(roomSummaryDetailsList.toImmutableList())
|
roomSummaryDetailsList.isNotEmpty() -> SearchBarResultState.Results(roomSummaryDetailsList.toImmutableList())
|
||||||
isSearchActive -> SearchBarResultState.NoResultsFound()
|
isSearchActive -> SearchBarResultState.NoResultsFound
|
||||||
else -> SearchBarResultState.Initial()
|
else -> SearchBarResultState.Initial
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -52,7 +52,7 @@ open class RoomSelectStateProvider : PreviewParameterProvider<RoomSelectState> {
|
|||||||
internal fun aRoomSelectState(
|
internal fun aRoomSelectState(
|
||||||
mode: RoomSelectMode = RoomSelectMode.Forward,
|
mode: RoomSelectMode = RoomSelectMode.Forward,
|
||||||
maxNumberOfRooms: Int = 10,
|
maxNumberOfRooms: Int = 10,
|
||||||
resultState: SearchBarResultState<ImmutableList<SelectRoomInfo>> = SearchBarResultState.Initial(),
|
resultState: SearchBarResultState<ImmutableList<SelectRoomInfo>> = SearchBarResultState.Initial,
|
||||||
searchQuery: String = "",
|
searchQuery: String = "",
|
||||||
isSearchActive: Boolean = false,
|
isSearchActive: Boolean = false,
|
||||||
selectedRooms: ImmutableList<SelectRoomInfo> = persistentListOf(),
|
selectedRooms: ImmutableList<SelectRoomInfo> = persistentListOf(),
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
<string name="a11y_collapse_message_text_field">"Minimise message text field"</string>
|
<string name="a11y_collapse_message_text_field">"Minimise message text field"</string>
|
||||||
<string name="a11y_create_poll_votes_allowed_decrease">"Decrease votes allowed per person"</string>
|
<string name="a11y_create_poll_votes_allowed_decrease">"Decrease votes allowed per person"</string>
|
||||||
<string name="a11y_create_poll_votes_allowed_increase">"Increase votes allowed per person"</string>
|
<string name="a11y_create_poll_votes_allowed_increase">"Increase votes allowed per person"</string>
|
||||||
|
<string name="a11y_custom_emoji">"Custom emoji"</string>
|
||||||
<string name="a11y_delete">"Delete"</string>
|
<string name="a11y_delete">"Delete"</string>
|
||||||
<plurals name="a11y_digits_entered">
|
<plurals name="a11y_digits_entered">
|
||||||
<item quantity="one">"%1$d digit entered"</item>
|
<item quantity="one">"%1$d digit entered"</item>
|
||||||
@@ -64,6 +65,7 @@
|
|||||||
<string name="a11y_start_call">"Start a call"</string>
|
<string name="a11y_start_call">"Start a call"</string>
|
||||||
<string name="a11y_start_video_call">"Start a video call"</string>
|
<string name="a11y_start_video_call">"Start a video call"</string>
|
||||||
<string name="a11y_start_voice_call">"Start a voice call"</string>
|
<string name="a11y_start_voice_call">"Start a voice call"</string>
|
||||||
|
<string name="a11y_status">"Status"</string>
|
||||||
<string name="a11y_thread_in_room">"Thread in %1$s"</string>
|
<string name="a11y_thread_in_room">"Thread in %1$s"</string>
|
||||||
<string name="a11y_threads_in_room">"Threads in %1$s"</string>
|
<string name="a11y_threads_in_room">"Threads in %1$s"</string>
|
||||||
<string name="a11y_tombstoned_room">"Tombstoned room"</string>
|
<string name="a11y_tombstoned_room">"Tombstoned room"</string>
|
||||||
@@ -445,7 +447,7 @@ Reason: %1$s."</string>
|
|||||||
<string name="common_world_readable_history">"Anyone can see history"</string>
|
<string name="common_world_readable_history">"Anyone can see history"</string>
|
||||||
<string name="common_you">"You"</string>
|
<string name="common_you">"You"</string>
|
||||||
<string name="content_scanner_not_found">"Download not available."</string>
|
<string name="content_scanner_not_found">"Download not available."</string>
|
||||||
<string name="content_scanner_not_found_title">"File not found"</string>
|
<string name="content_scanner_not_found_title">"Something went wrong"</string>
|
||||||
<string name="content_scanner_scanning">"Scanning…"</string>
|
<string name="content_scanner_scanning">"Scanning…"</string>
|
||||||
<string name="content_scanner_unsafe_message">"Preview and download have been disabled."</string>
|
<string name="content_scanner_unsafe_message">"Preview and download have been disabled."</string>
|
||||||
<string name="content_scanner_unsafe_title">"The file is not safe"</string>
|
<string name="content_scanner_unsafe_title">"The file is not safe"</string>
|
||||||
@@ -517,7 +519,7 @@ Are you sure you want to continue?"</string>
|
|||||||
<item quantity="other">"%1$d people"</item>
|
<item quantity="other">"%1$d people"</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="screen_live_location_sheet_title">"On the map"</string>
|
<string name="screen_live_location_sheet_title">"On the map"</string>
|
||||||
<string name="screen_local_network_opt_in_subtitle">"Your homeserver is on your local network. To connect, Element needs permission to reach devices on this network."</string>
|
<string name="screen_local_network_opt_in_subtitle">"Your homeserver is on your local network. To connect, %1$s needs permission to reach devices on this network."</string>
|
||||||
<string name="screen_local_network_opt_in_title">"Allow access to local network"</string>
|
<string name="screen_local_network_opt_in_title">"Allow access to local network"</string>
|
||||||
<string name="screen_media_picker_error_failed_selection">"Failed selecting media, please try again."</string>
|
<string name="screen_media_picker_error_failed_selection">"Failed selecting media, please try again."</string>
|
||||||
<string name="screen_pinned_timeline_empty_state_description">"Press on a message and choose “%1$s” to include here."</string>
|
<string name="screen_pinned_timeline_empty_state_description">"Press on a message and choose “%1$s” to include here."</string>
|
||||||
@@ -550,6 +552,14 @@ Are you sure you want to continue?"</string>
|
|||||||
<string name="screen_room_pinned_banner_loading_description">"Loading message…"</string>
|
<string name="screen_room_pinned_banner_loading_description">"Loading message…"</string>
|
||||||
<string name="screen_room_pinned_banner_view_all_button_title">"View All"</string>
|
<string name="screen_room_pinned_banner_view_all_button_title">"View All"</string>
|
||||||
<string name="screen_room_title">"Chat"</string>
|
<string name="screen_room_title">"Chat"</string>
|
||||||
|
<string name="screen_settings_user_status_away">"Away"</string>
|
||||||
|
<string name="screen_settings_user_status_be_right_back">"Be right back"</string>
|
||||||
|
<string name="screen_settings_user_status_custom">"Custom…"</string>
|
||||||
|
<string name="screen_settings_user_status_custom_hint">"Custom status…"</string>
|
||||||
|
<string name="screen_settings_user_status_focus_time">"Focus time"</string>
|
||||||
|
<string name="screen_settings_user_status_in_a_meeting">"In a meeting"</string>
|
||||||
|
<string name="screen_settings_user_status_on_the_road">"On the road"</string>
|
||||||
|
<string name="screen_settings_user_status_placeholder">"What\'s your status?"</string>
|
||||||
<string name="screen_share_location_title">"Share location"</string>
|
<string name="screen_share_location_title">"Share location"</string>
|
||||||
<string name="screen_share_my_location_action">"Share my location"</string>
|
<string name="screen_share_my_location_action">"Share my location"</string>
|
||||||
<string name="screen_share_open_apple_maps">"Open in Apple Maps"</string>
|
<string name="screen_share_open_apple_maps">"Open in Apple Maps"</string>
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Reference in New Issue
Block a user