mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 12:07:28 +00:00
Merge branch 'develop' into renovate/actions-setup-java-5.x
This commit is contained in:
@@ -85,6 +85,7 @@ fun LoggedInView(
|
||||
}
|
||||
|
||||
LocalNetworkPermissionDialogView(
|
||||
appName = state.appName,
|
||||
dialog = state.localNetworkPermissionDialog,
|
||||
onSubmit = { state.eventSink(LoggedInEvents.RequestLocationNetworkPermission) },
|
||||
onDismiss = { state.eventSink(LoggedInEvents.DismissLocalNetworkPermissionPrompt) },
|
||||
|
||||
+4
-4
@@ -88,7 +88,7 @@ class DefaultInvitePeoplePresenter(
|
||||
override fun present(): InvitePeopleState {
|
||||
val roomMembers = remember { mutableStateOf<AsyncData<ImmutableList<RoomMember>>>(AsyncData.Loading()) }
|
||||
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()
|
||||
var searchActive by rememberSaveable { mutableStateOf(false) }
|
||||
val showSearchLoader = rememberSaveable { mutableStateOf(false) }
|
||||
@@ -332,15 +332,15 @@ class DefaultInvitePeoplePresenter(
|
||||
showSearchLoader: MutableState<Boolean>,
|
||||
searchQuery: String,
|
||||
) = withContext(coroutineDispatchers.io) {
|
||||
searchResults.value = SearchBarResultState.Initial()
|
||||
searchResults.value = SearchBarResultState.Initial
|
||||
showSearchLoader.value = false
|
||||
val joinedMembers = roomMembers.value.dataOrNull().orEmpty()
|
||||
|
||||
userRepository.search(searchQuery).onEach { state ->
|
||||
showSearchLoader.value = state.isSearching
|
||||
searchResults.value = when {
|
||||
state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial()
|
||||
state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound()
|
||||
state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial
|
||||
state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound
|
||||
else -> SearchBarResultState.Results(state.results.map { result ->
|
||||
val existingMembership = joinedMembers.firstOrNull { j -> j.userId == result.matrixUser.userId }?.membership
|
||||
val isJoined = existingMembership == RoomMembershipState.JOIN
|
||||
|
||||
+2
-2
@@ -33,7 +33,7 @@ internal class DefaultInvitePeopleStateProvider : PreviewParameterProvider<Defau
|
||||
aDefaultInvitePeopleState(canInvite = true, selectedUsers = aMatrixUserList().toImmutableList()),
|
||||
aDefaultInvitePeopleState(isSearchActive = true, searchQuery = "some query"),
|
||||
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(
|
||||
isSearchActive = true,
|
||||
canInvite = true,
|
||||
@@ -115,7 +115,7 @@ private fun aDefaultInvitePeopleState(
|
||||
room: AsyncData<Unit> = AsyncData.Success(Unit),
|
||||
canInvite: Boolean = false,
|
||||
searchQuery: String = "",
|
||||
searchResults: SearchBarResultState<ImmutableList<InvitableUser>> = SearchBarResultState.Initial(),
|
||||
searchResults: SearchBarResultState<ImmutableList<InvitableUser>> = SearchBarResultState.Initial,
|
||||
selectedUsers: ImmutableList<MatrixUser> = persistentListOf(),
|
||||
isSearchActive: Boolean = false,
|
||||
showSearchLoader: Boolean = false,
|
||||
|
||||
+4
-8
@@ -95,7 +95,7 @@ internal class DefaultInvitePeoplePresenterTest {
|
||||
resultState.searchQuery.setTextAndPlaceCursorAtEnd("some query")
|
||||
assertThat(awaitItemAsDefault().searchQuery.text.toString()).isEqualTo("some query")
|
||||
resultState.eventSink(InvitePeopleEvents.CloseSearch)
|
||||
skipItems(2)
|
||||
skipItems(1)
|
||||
awaitItemAsDefault().also {
|
||||
assertThat(it.isSearchActive).isFalse()
|
||||
assertThat(it.searchQuery.text.toString()).isEmpty()
|
||||
@@ -116,7 +116,7 @@ internal class DefaultInvitePeoplePresenterTest {
|
||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd("some query")
|
||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||
repository.emitState(UserSearchResultState(results = emptyList(), isSearching = true))
|
||||
skipItems(3)
|
||||
skipItems(2)
|
||||
awaitItemAsDefault().also { state ->
|
||||
assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
|
||||
assertThat(state.showSearchLoader).isTrue()
|
||||
@@ -145,7 +145,6 @@ internal class DefaultInvitePeoplePresenterTest {
|
||||
|
||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||
repository.emitStateWithUsers(users = aMatrixUserList())
|
||||
skipItems(1)
|
||||
|
||||
val resultState = awaitItemAsDefault()
|
||||
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
||||
@@ -198,7 +197,6 @@ internal class DefaultInvitePeoplePresenterTest {
|
||||
|
||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||
repository.emitStateWithUsers(users = aMatrixUserList())
|
||||
skipItems(1)
|
||||
|
||||
val resultState = awaitItemAsDefault()
|
||||
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
||||
@@ -265,7 +263,6 @@ internal class DefaultInvitePeoplePresenterTest {
|
||||
it
|
||||
)
|
||||
})
|
||||
skipItems(1)
|
||||
|
||||
val resultState = awaitItemAsDefault()
|
||||
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
||||
@@ -329,7 +326,7 @@ internal class DefaultInvitePeoplePresenterTest {
|
||||
|
||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||
repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser)
|
||||
skipItems(2)
|
||||
skipItems(1)
|
||||
|
||||
val resultState = awaitItemAsDefault()
|
||||
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
||||
@@ -366,7 +363,6 @@ internal class DefaultInvitePeoplePresenterTest {
|
||||
|
||||
assertThat(repository.providedQuery).isEqualTo("some query")
|
||||
repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser)
|
||||
skipItems(1)
|
||||
awaitItemAsDefault().also { state ->
|
||||
// selectedUser is not selected
|
||||
assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
|
||||
@@ -732,7 +728,7 @@ internal class DefaultInvitePeoplePresenterTest {
|
||||
isSearching = true
|
||||
)
|
||||
)
|
||||
skipItems(3)
|
||||
skipItems(2)
|
||||
|
||||
awaitItemAsDefault().run {
|
||||
assertThat(selectedUsers).containsExactly(alice, bob, charlie)
|
||||
|
||||
+1
@@ -123,6 +123,7 @@ fun ChangeServerView(
|
||||
AsyncData.Uninitialized -> Unit
|
||||
}
|
||||
LocalNetworkPermissionDialogView(
|
||||
appName = LocalBuildMeta.current.applicationName,
|
||||
dialog = state.localNetworkPermissionDialog,
|
||||
onSubmit = {
|
||||
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.preview.ElementPreview
|
||||
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.Scaffold
|
||||
import io.element.android.libraries.designsystem.theme.components.TopAppBar
|
||||
@@ -138,6 +139,7 @@ fun ChooseAccountProviderView(
|
||||
}
|
||||
}
|
||||
LocalNetworkPermissionDialogView(
|
||||
appName = LocalBuildMeta.current.applicationName,
|
||||
dialog = state.loginModeState.localNetworkPermissionDialog,
|
||||
onSubmit = {
|
||||
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.preview.ElementPreview
|
||||
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.OutlinedButton
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
@@ -207,6 +208,7 @@ fun LoginWithClassicView(
|
||||
onCreateAccountContinue = onCreateAccountContinue,
|
||||
)
|
||||
LocalNetworkPermissionDialogView(
|
||||
appName = LocalBuildMeta.current.applicationName,
|
||||
dialog = state.loginModeState.localNetworkPermissionDialog,
|
||||
onSubmit = {
|
||||
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.preview.ElementPreview
|
||||
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.TextButton
|
||||
import io.element.android.libraries.matrix.api.auth.OAuthDetails
|
||||
@@ -112,6 +113,7 @@ fun ConfirmAccountProviderView(
|
||||
}
|
||||
|
||||
LocalNetworkPermissionDialogView(
|
||||
appName = LocalBuildMeta.current.applicationName,
|
||||
dialog = state.loginModeState.localNetworkPermissionDialog,
|
||||
onSubmit = {
|
||||
state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission)
|
||||
|
||||
+1
@@ -87,6 +87,7 @@ fun OnBoardingView(
|
||||
onCreateAccountContinue = onCreateAccountContinue,
|
||||
)
|
||||
LocalNetworkPermissionDialogView(
|
||||
appName = state.productionApplicationName,
|
||||
dialog = state.loginModeState.localNetworkPermissionDialog,
|
||||
onSubmit = {
|
||||
state.loginModeState.eventSink(LoginModeEvent.RequestLocalNetworkPermission)
|
||||
|
||||
+2
-2
@@ -77,7 +77,7 @@ class ChangeRolesPresenter(
|
||||
val queryState = rememberTextFieldState()
|
||||
var searchActive by rememberSaveable { mutableStateOf(false) }
|
||||
var searchResults by remember {
|
||||
mutableStateOf<SearchBarResultState<MembersByRole>>(SearchBarResultState.Initial())
|
||||
mutableStateOf<SearchBarResultState<MembersByRole>>(SearchBarResultState.Initial)
|
||||
}
|
||||
val selectedUsers = remember {
|
||||
mutableStateOf<ImmutableList<MatrixUser>>(persistentListOf())
|
||||
@@ -118,7 +118,7 @@ class ChangeRolesPresenter(
|
||||
.groupedByRole()
|
||||
|
||||
searchResults = if (results.isEmpty()) {
|
||||
SearchBarResultState.NoResultsFound()
|
||||
SearchBarResultState.NoResultsFound
|
||||
} else {
|
||||
SearchBarResultState.Results(results)
|
||||
}
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ internal fun aChangeRolesState(
|
||||
role: RoomMember.Role = RoomMember.Role.Admin,
|
||||
searchQuery: String = "",
|
||||
isSearchActive: Boolean = false,
|
||||
searchResults: SearchBarResultState<MembersByRole> = SearchBarResultState.NoResultsFound(),
|
||||
searchResults: SearchBarResultState<MembersByRole> = SearchBarResultState.NoResultsFound,
|
||||
selectedUsers: ImmutableList<MatrixUser> = persistentListOf(),
|
||||
hasPendingChanges: Boolean = false,
|
||||
savingState: AsyncAction<Boolean> = AsyncAction.Uninitialized,
|
||||
|
||||
+2
-2
@@ -66,8 +66,8 @@ class AddRoomToSpacePresenter(
|
||||
derivedStateOf {
|
||||
when {
|
||||
filteredRooms.isNotEmpty() -> SearchBarResultState.Results(filteredRooms)
|
||||
isSearchActive && searchQuery.text.isNotEmpty() -> SearchBarResultState.NoResultsFound<ImmutableList<SelectRoomInfo>>()
|
||||
else -> SearchBarResultState.Initial<ImmutableList<SelectRoomInfo>>()
|
||||
isSearchActive && searchQuery.text.isNotEmpty() -> SearchBarResultState.NoResultsFound
|
||||
else -> SearchBarResultState.Initial
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -40,7 +40,7 @@ internal class AddRoomToSpaceStateProvider : PreviewParameterProvider<AddRoomToS
|
||||
anAddRoomToSpaceState(
|
||||
isSearchActive = true,
|
||||
searchQuery = "unknown",
|
||||
searchResults = SearchBarResultState.NoResultsFound(),
|
||||
searchResults = SearchBarResultState.NoResultsFound,
|
||||
),
|
||||
// With selected rooms
|
||||
anAddRoomToSpaceState(
|
||||
@@ -62,7 +62,7 @@ internal class AddRoomToSpaceStateProvider : PreviewParameterProvider<AddRoomToS
|
||||
|
||||
internal fun anAddRoomToSpaceState(
|
||||
searchQuery: String = "",
|
||||
searchResults: SearchBarResultState<ImmutableList<SelectRoomInfo>> = SearchBarResultState.Initial(),
|
||||
searchResults: SearchBarResultState<ImmutableList<SelectRoomInfo>> = SearchBarResultState.Initial,
|
||||
selectedRooms: ImmutableList<SelectRoomInfo> = persistentListOf(),
|
||||
isSearchActive: Boolean = false,
|
||||
saveAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
|
||||
|
||||
+4
-4
@@ -67,19 +67,19 @@ class DefaultUserListPresenter(
|
||||
val selectedUsers by userListDataStore.selectedUsers.collectAsState(emptyList())
|
||||
val queryState = rememberTextFieldState()
|
||||
var searchResults: SearchBarResultState<ImmutableList<UserSearchResult>> by remember {
|
||||
mutableStateOf(SearchBarResultState.Initial())
|
||||
mutableStateOf(SearchBarResultState.Initial)
|
||||
}
|
||||
var showSearchLoader by remember { mutableStateOf(false) }
|
||||
|
||||
val searchQuery = queryState.text.toString()
|
||||
LaunchedEffect(searchQuery) {
|
||||
searchResults = SearchBarResultState.Initial()
|
||||
searchResults = SearchBarResultState.Initial
|
||||
showSearchLoader = false
|
||||
userRepository.search(searchQuery).onEach { state ->
|
||||
showSearchLoader = state.isSearching
|
||||
searchResults = when {
|
||||
state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial()
|
||||
state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound()
|
||||
state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial
|
||||
state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound
|
||||
else -> SearchBarResultState.Results(state.results.toImmutableList())
|
||||
}
|
||||
}.launchIn(this)
|
||||
|
||||
+2
-2
@@ -47,7 +47,7 @@ open class UserListStateProvider : PreviewParameterProvider<UserListState> {
|
||||
aUserListState(
|
||||
isSearchActive = true,
|
||||
searchQuery = "something-with-no-results",
|
||||
searchResults = SearchBarResultState.NoResultsFound()
|
||||
searchResults = SearchBarResultState.NoResultsFound
|
||||
),
|
||||
aUserListState(
|
||||
isSearchActive = true,
|
||||
@@ -63,7 +63,7 @@ open class UserListStateProvider : PreviewParameterProvider<UserListState> {
|
||||
fun aUserListState(
|
||||
searchQuery: String = "",
|
||||
isSearchActive: Boolean = false,
|
||||
searchResults: SearchBarResultState<ImmutableList<UserSearchResult>> = SearchBarResultState.Initial(),
|
||||
searchResults: SearchBarResultState<ImmutableList<UserSearchResult>> = SearchBarResultState.Initial,
|
||||
selectedUsers: List<MatrixUser> = emptyList(),
|
||||
showSearchLoader: Boolean = false,
|
||||
selectionMode: SelectionMode = SelectionMode.Single,
|
||||
|
||||
+2
-10
@@ -40,7 +40,6 @@ class DefaultUserListPresenterTest {
|
||||
FakeMatrixClient(),
|
||||
)
|
||||
presenter.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.searchQuery.text.toString()).isEmpty()
|
||||
assertThat(initialState.isMultiSelectionEnabled).isFalse()
|
||||
@@ -60,7 +59,6 @@ class DefaultUserListPresenterTest {
|
||||
FakeMatrixClient(),
|
||||
)
|
||||
presenter.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
assertThat(initialState.searchQuery.text.toString()).isEmpty()
|
||||
assertThat(initialState.isMultiSelectionEnabled).isTrue()
|
||||
@@ -80,7 +78,6 @@ class DefaultUserListPresenterTest {
|
||||
FakeMatrixClient(),
|
||||
)
|
||||
presenter.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
|
||||
initialState.eventSink(UserListEvents.OnSearchActiveChanged(true))
|
||||
@@ -90,13 +87,11 @@ class DefaultUserListPresenterTest {
|
||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd(matrixIdQuery)
|
||||
assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(matrixIdQuery)
|
||||
assertThat(userRepository.providedQuery).isEqualTo(matrixIdQuery)
|
||||
skipItems(1)
|
||||
|
||||
val notMatrixIdQuery = "name"
|
||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd(notMatrixIdQuery)
|
||||
assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(notMatrixIdQuery)
|
||||
assertThat(userRepository.providedQuery).isEqualTo(notMatrixIdQuery)
|
||||
skipItems(1)
|
||||
|
||||
initialState.eventSink(UserListEvents.OnSearchActiveChanged(false))
|
||||
assertThat(awaitItem().isSearchActive).isFalse()
|
||||
@@ -115,13 +110,12 @@ class DefaultUserListPresenterTest {
|
||||
FakeMatrixClient(),
|
||||
)
|
||||
presenter.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
|
||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice")
|
||||
assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
|
||||
assertThat(userRepository.providedQuery).isEqualTo("alice")
|
||||
skipItems(2)
|
||||
skipItems(1)
|
||||
|
||||
// When the user repository emits a result, it's copied to the state
|
||||
val result = UserSearchResultState(
|
||||
@@ -166,13 +160,12 @@ class DefaultUserListPresenterTest {
|
||||
FakeMatrixClient(),
|
||||
)
|
||||
presenter.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
|
||||
initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice")
|
||||
assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
|
||||
assertThat(userRepository.providedQuery).isEqualTo("alice")
|
||||
skipItems(2)
|
||||
skipItems(1)
|
||||
|
||||
// When the results list is empty, the state is set to NoResults
|
||||
userRepository.emitState(UserSearchResultState(results = emptyList(), isSearching = false))
|
||||
@@ -190,7 +183,6 @@ class DefaultUserListPresenterTest {
|
||||
FakeMatrixClient(),
|
||||
)
|
||||
presenter.test {
|
||||
skipItems(1)
|
||||
val initialState = awaitItem()
|
||||
|
||||
val userA = aMatrixUser("@userA:domain", "A")
|
||||
|
||||
@@ -51,7 +51,7 @@ telephoto = "0.19.0"
|
||||
haze = "1.7.2"
|
||||
|
||||
# Dependency analysis
|
||||
dependencyAnalysis = "3.16.1"
|
||||
dependencyAnalysis = "3.17.0"
|
||||
|
||||
# DI
|
||||
metro = "1.3.2"
|
||||
|
||||
+7
-7
@@ -59,7 +59,7 @@ fun <T> SearchBar(
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
showBackButton: Boolean = true,
|
||||
resultState: SearchBarResultState<T> = SearchBarResultState.Initial(),
|
||||
resultState: SearchBarResultState<T> = SearchBarResultState.Initial,
|
||||
shape: Shape = SearchBarDefaults.inputFieldShape,
|
||||
tonalElevation: Dp = SearchBarDefaults.TonalElevation,
|
||||
windowInsets: WindowInsets = SearchBarDefaults.windowInsets,
|
||||
@@ -134,7 +134,7 @@ fun <T> SearchBar(
|
||||
resultHandler(resultState.results)
|
||||
}
|
||||
|
||||
is SearchBarResultState.NoResultsFound<T> -> {
|
||||
is SearchBarResultState.NoResultsFound -> {
|
||||
// No results found, show a message
|
||||
Spacer(Modifier.size(80.dp))
|
||||
|
||||
@@ -200,12 +200,12 @@ object ElementSearchBarDefaults {
|
||||
}
|
||||
|
||||
@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). */
|
||||
class Initial<T> : SearchBarResultState<T>
|
||||
data object Initial : SearchBarResultState<Nothing>
|
||||
|
||||
/** 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. */
|
||||
data class Results<T>(val results: T) : SearchBarResultState<T>
|
||||
@@ -249,7 +249,7 @@ internal fun SearchBarActiveWithNoResultsPreview() = ElementThemedPreview {
|
||||
ContentToPreview(
|
||||
initialQuery = "search term",
|
||||
active = true,
|
||||
resultState = SearchBarResultState.NoResultsFound<String>(),
|
||||
resultState = SearchBarResultState.NoResultsFound,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ private fun ContentToPreview(
|
||||
initialQuery: String = "",
|
||||
active: Boolean = false,
|
||||
showBackButton: Boolean = true,
|
||||
resultState: SearchBarResultState<String> = SearchBarResultState.Initial(),
|
||||
resultState: SearchBarResultState<String> = SearchBarResultState.Initial,
|
||||
contentPrefix: @Composable ColumnScope.() -> Unit = {},
|
||||
contentSuffix: @Composable ColumnScope.() -> Unit = {},
|
||||
resultHandler: @Composable ColumnScope.(String) -> Unit = {},
|
||||
|
||||
+2
-6
@@ -55,7 +55,7 @@ class DefaultEmojiPickerPresenter(
|
||||
override fun present(): EmojiPickerState {
|
||||
val queryState = rememberTextFieldState()
|
||||
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 storeDeferred = async { emojibaseProvider.getStore() }
|
||||
@@ -93,11 +93,7 @@ class DefaultEmojiPickerPresenter(
|
||||
val searchQuery = queryState.text.toString()
|
||||
LaunchedEffect(searchQuery, data) {
|
||||
if (searchQuery.isEmpty() || data.allEmojis.isEmpty()) {
|
||||
// `SearchBarResultState.Initial` has no `equals` override, so reassigning a new instance
|
||||
// would trigger a redundant emission each time this effect re-runs while the query is empty.
|
||||
if (emojiResults !is SearchBarResultState.Initial) {
|
||||
emojiResults = SearchBarResultState.Initial()
|
||||
}
|
||||
emojiResults = SearchBarResultState.Initial
|
||||
return@LaunchedEffect
|
||||
}
|
||||
delay(100.milliseconds)
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ internal fun aDefaultEmojiPickerState(
|
||||
}.toImmutableList(),
|
||||
searchQuery: String = "",
|
||||
isSearchActive: Boolean = false,
|
||||
searchResults: SearchBarResultState<ImmutableList<Emoji>> = SearchBarResultState.Initial(),
|
||||
searchResults: SearchBarResultState<ImmutableList<Emoji>> = SearchBarResultState.Initial,
|
||||
eventSink: (EmojiPickerEvent) -> Unit = {},
|
||||
) = DefaultEmojiPickerState(
|
||||
categories = categories,
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@Composable
|
||||
fun LocalNetworkPermissionDialogView(
|
||||
appName: String,
|
||||
dialog: LocalNetworkPermissionDialog,
|
||||
onSubmit: () -> Unit,
|
||||
onDismiss: () -> Unit,
|
||||
@@ -27,7 +28,7 @@ fun LocalNetworkPermissionDialogView(
|
||||
}
|
||||
ConfirmationDialog(
|
||||
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),
|
||||
cancelText = stringResource(CommonStrings.action_not_now),
|
||||
onSubmitClick = onSubmit,
|
||||
|
||||
+2
-2
@@ -65,8 +65,8 @@ class RoomSelectPresenter(
|
||||
derivedStateOf {
|
||||
when {
|
||||
roomSummaryDetailsList.isNotEmpty() -> SearchBarResultState.Results(roomSummaryDetailsList.toImmutableList())
|
||||
isSearchActive -> SearchBarResultState.NoResultsFound()
|
||||
else -> SearchBarResultState.Initial()
|
||||
isSearchActive -> SearchBarResultState.NoResultsFound
|
||||
else -> SearchBarResultState.Initial
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ open class RoomSelectStateProvider : PreviewParameterProvider<RoomSelectState> {
|
||||
internal fun aRoomSelectState(
|
||||
mode: RoomSelectMode = RoomSelectMode.Forward,
|
||||
maxNumberOfRooms: Int = 10,
|
||||
resultState: SearchBarResultState<ImmutableList<SelectRoomInfo>> = SearchBarResultState.Initial(),
|
||||
resultState: SearchBarResultState<ImmutableList<SelectRoomInfo>> = SearchBarResultState.Initial,
|
||||
searchQuery: String = "",
|
||||
isSearchActive: Boolean = false,
|
||||
selectedRooms: ImmutableList<SelectRoomInfo> = persistentListOf(),
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<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_increase">"Increase votes allowed per person"</string>
|
||||
<string name="a11y_custom_emoji">"Custom emoji"</string>
|
||||
<string name="a11y_delete">"Delete"</string>
|
||||
<plurals name="a11y_digits_entered">
|
||||
<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_video_call">"Start a video 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_threads_in_room">"Threads in %1$s"</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_you">"You"</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_unsafe_message">"Preview and download have been disabled."</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>
|
||||
</plurals>
|
||||
<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_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>
|
||||
@@ -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_view_all_button_title">"View All"</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_my_location_action">"Share my location"</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