Room list: tweak UI and add overflow menu with report bug and invite friends action.
Extract invite friends action to a use case to avoid copy paste.
This commit is contained in:
parent
e7e225dd3a
commit
82e566175a
12 changed files with 180 additions and 38 deletions
|
|
@ -222,6 +222,10 @@ class LoggedInFlowNode @AssistedInject constructor(
|
||||||
override fun onRoomSettingsClicked(roomId: RoomId) {
|
override fun onRoomSettingsClicked(roomId: RoomId) {
|
||||||
backstack.push(NavTarget.Room(roomId, initialElement = RoomFlowNode.NavTarget.RoomDetails))
|
backstack.push(NavTarget.Room(roomId, initialElement = RoomFlowNode.NavTarget.RoomDetails))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onReportBugClicked() {
|
||||||
|
plugins<Callback>().forEach { it.onOpenBugReport() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
roomListEntryPoint
|
roomListEntryPoint
|
||||||
.nodeBuilder(this, buildContext)
|
.nodeBuilder(this, buildContext)
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ dependencies {
|
||||||
implementation(projects.libraries.designsystem)
|
implementation(projects.libraries.designsystem)
|
||||||
implementation(projects.libraries.uiStrings)
|
implementation(projects.libraries.uiStrings)
|
||||||
implementation(projects.libraries.androidutils)
|
implementation(projects.libraries.androidutils)
|
||||||
|
implementation(projects.libraries.deeplink)
|
||||||
implementation(projects.libraries.mediapickers.api)
|
implementation(projects.libraries.mediapickers.api)
|
||||||
implementation(projects.libraries.mediaupload.api)
|
implementation(projects.libraries.mediaupload.api)
|
||||||
implementation(projects.libraries.usersearch.impl)
|
implementation(projects.libraries.usersearch.impl)
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
package io.element.android.features.createroom.impl.root
|
package io.element.android.features.createroom.impl.root
|
||||||
|
|
||||||
import android.content.Context
|
import android.app.Activity
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
|
@ -29,24 +29,18 @@ import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import im.vector.app.features.analytics.plan.MobileScreen
|
import im.vector.app.features.analytics.plan.MobileScreen
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.libraries.androidutils.system.startSharePlainTextIntent
|
import io.element.android.libraries.deeplink.usecase.InviteFriendsUseCase
|
||||||
import io.element.android.libraries.core.meta.BuildMeta
|
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
|
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
|
||||||
import io.element.android.services.analytics.api.AnalyticsService
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
import timber.log.Timber
|
|
||||||
|
|
||||||
@ContributesNode(SessionScope::class)
|
@ContributesNode(SessionScope::class)
|
||||||
class CreateRoomRootNode @AssistedInject constructor(
|
class CreateRoomRootNode @AssistedInject constructor(
|
||||||
@Assisted buildContext: BuildContext,
|
@Assisted buildContext: BuildContext,
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
private val presenter: CreateRoomRootPresenter,
|
private val presenter: CreateRoomRootPresenter,
|
||||||
private val matrixClient: MatrixClient,
|
|
||||||
private val buildMeta: BuildMeta,
|
|
||||||
private val analyticsService: AnalyticsService,
|
private val analyticsService: AnalyticsService,
|
||||||
|
private val inviteFriendsUseCase: InviteFriendsUseCase,
|
||||||
) : Node(buildContext, plugins = plugins) {
|
) : Node(buildContext, plugins = plugins) {
|
||||||
|
|
||||||
interface Callback : Plugin {
|
interface Callback : Plugin {
|
||||||
|
|
@ -73,31 +67,18 @@ class CreateRoomRootNode @AssistedInject constructor(
|
||||||
@Composable
|
@Composable
|
||||||
override fun View(modifier: Modifier) {
|
override fun View(modifier: Modifier) {
|
||||||
val state = presenter.present()
|
val state = presenter.present()
|
||||||
val context = LocalContext.current
|
val activity = LocalContext.current as Activity
|
||||||
CreateRoomRootView(
|
CreateRoomRootView(
|
||||||
state = state,
|
state = state,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
onClosePressed = this::navigateUp,
|
onClosePressed = this::navigateUp,
|
||||||
onNewRoomClicked = callback::onCreateNewRoom,
|
onNewRoomClicked = callback::onCreateNewRoom,
|
||||||
onOpenDM = callback::onStartChatSuccess,
|
onOpenDM = callback::onStartChatSuccess,
|
||||||
onInviteFriendsClicked = { invitePeople(context) },
|
onInviteFriendsClicked = { invitePeople(activity) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun invitePeople(context: Context) {
|
private fun invitePeople(activity: Activity) {
|
||||||
val permalinkResult = PermalinkBuilder.permalinkForUser(matrixClient.sessionId)
|
inviteFriendsUseCase.execute(activity)
|
||||||
permalinkResult.onSuccess { permalink ->
|
|
||||||
val appName = buildMeta.applicationName
|
|
||||||
startSharePlainTextIntent(
|
|
||||||
context = context,
|
|
||||||
activityResultLauncher = null,
|
|
||||||
chooserTitle = context.getString(CommonStrings.action_invite_friends),
|
|
||||||
text = context.getString(CommonStrings.invite_friends_text, appName, permalink),
|
|
||||||
extraTitle = context.getString(CommonStrings.invite_friends_rich_title, appName),
|
|
||||||
noActivityFoundMessage = context.getString(io.element.android.libraries.androidutils.R.string.error_no_compatible_app_found)
|
|
||||||
)
|
|
||||||
}.onFailure {
|
|
||||||
Timber.e(it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ interface RoomListEntryPoint : FeatureEntryPoint {
|
||||||
fun onSessionVerificationClicked()
|
fun onSessionVerificationClicked()
|
||||||
fun onInvitesClicked()
|
fun onInvitesClicked()
|
||||||
fun onRoomSettingsClicked(roomId: RoomId)
|
fun onRoomSettingsClicked(roomId: RoomId)
|
||||||
|
fun onReportBugClicked()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ dependencies {
|
||||||
implementation(projects.libraries.uiStrings)
|
implementation(projects.libraries.uiStrings)
|
||||||
implementation(projects.libraries.dateformatter.api)
|
implementation(projects.libraries.dateformatter.api)
|
||||||
implementation(projects.libraries.eventformatter.api)
|
implementation(projects.libraries.eventformatter.api)
|
||||||
|
implementation(projects.libraries.deeplink)
|
||||||
implementation(projects.features.invitelist.api)
|
implementation(projects.features.invitelist.api)
|
||||||
implementation(projects.features.networkmonitor.api)
|
implementation(projects.features.networkmonitor.api)
|
||||||
implementation(projects.features.leaveroom.api)
|
implementation(projects.features.leaveroom.api)
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,10 @@
|
||||||
|
|
||||||
package io.element.android.features.roomlist.impl
|
package io.element.android.features.roomlist.impl
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import com.bumble.appyx.core.modality.BuildContext
|
import com.bumble.appyx.core.modality.BuildContext
|
||||||
import com.bumble.appyx.core.node.Node
|
import com.bumble.appyx.core.node.Node
|
||||||
import com.bumble.appyx.core.plugin.Plugin
|
import com.bumble.appyx.core.plugin.Plugin
|
||||||
|
|
@ -26,6 +28,8 @@ import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import io.element.android.anvilannotations.ContributesNode
|
import io.element.android.anvilannotations.ContributesNode
|
||||||
import io.element.android.features.roomlist.api.RoomListEntryPoint
|
import io.element.android.features.roomlist.api.RoomListEntryPoint
|
||||||
|
import io.element.android.features.roomlist.impl.components.RoomListMenuAction
|
||||||
|
import io.element.android.libraries.deeplink.usecase.InviteFriendsUseCase
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
|
|
||||||
|
|
@ -33,7 +37,8 @@ import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
class RoomListNode @AssistedInject constructor(
|
class RoomListNode @AssistedInject constructor(
|
||||||
@Assisted buildContext: BuildContext,
|
@Assisted buildContext: BuildContext,
|
||||||
@Assisted plugins: List<Plugin>,
|
@Assisted plugins: List<Plugin>,
|
||||||
private val presenter: RoomListPresenter,
|
private val presenter: RoomListPresenter,
|
||||||
|
private val inviteFriendsUseCase: InviteFriendsUseCase,
|
||||||
) : Node(buildContext, plugins = plugins) {
|
) : Node(buildContext, plugins = plugins) {
|
||||||
|
|
||||||
private fun onRoomClicked(roomId: RoomId) {
|
private fun onRoomClicked(roomId: RoomId) {
|
||||||
|
|
@ -60,9 +65,21 @@ class RoomListNode @AssistedInject constructor(
|
||||||
plugins<RoomListEntryPoint.Callback>().forEach { it.onRoomSettingsClicked(roomId) }
|
plugins<RoomListEntryPoint.Callback>().forEach { it.onRoomSettingsClicked(roomId) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onMenuActionClicked(activity: Activity, roomListMenuAction: RoomListMenuAction) {
|
||||||
|
when (roomListMenuAction) {
|
||||||
|
RoomListMenuAction.InviteFriends -> {
|
||||||
|
inviteFriendsUseCase.execute(activity)
|
||||||
|
}
|
||||||
|
RoomListMenuAction.ReportBug -> {
|
||||||
|
plugins<RoomListEntryPoint.Callback>().forEach { it.onReportBugClicked() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun View(modifier: Modifier) {
|
override fun View(modifier: Modifier) {
|
||||||
val state = presenter.present()
|
val state = presenter.present()
|
||||||
|
val activity = LocalContext.current as Activity
|
||||||
RoomListView(
|
RoomListView(
|
||||||
state = state,
|
state = state,
|
||||||
onRoomClicked = this::onRoomClicked,
|
onRoomClicked = this::onRoomClicked,
|
||||||
|
|
@ -71,6 +88,7 @@ class RoomListNode @AssistedInject constructor(
|
||||||
onVerifyClicked = this::onSessionVerificationClicked,
|
onVerifyClicked = this::onSessionVerificationClicked,
|
||||||
onInvitesClicked = this::onInvitesClicked,
|
onInvitesClicked = this::onInvitesClicked,
|
||||||
onRoomSettingsClicked = this::onRoomSettingsClicked,
|
onRoomSettingsClicked = this::onRoomSettingsClicked,
|
||||||
|
onMenuActionClicked = { onMenuActionClicked(activity, it) },
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import io.element.android.features.leaveroom.api.LeaveRoomView
|
import io.element.android.features.leaveroom.api.LeaveRoomView
|
||||||
import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorView
|
import io.element.android.features.networkmonitor.api.ui.ConnectivityIndicatorView
|
||||||
|
import io.element.android.features.roomlist.impl.components.RoomListMenuAction
|
||||||
import io.element.android.features.roomlist.impl.components.RoomListTopBar
|
import io.element.android.features.roomlist.impl.components.RoomListTopBar
|
||||||
import io.element.android.features.roomlist.impl.components.RoomSummaryRow
|
import io.element.android.features.roomlist.impl.components.RoomSummaryRow
|
||||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||||
|
|
@ -95,6 +96,7 @@ fun RoomListView(
|
||||||
onCreateRoomClicked: () -> Unit,
|
onCreateRoomClicked: () -> Unit,
|
||||||
onInvitesClicked: () -> Unit,
|
onInvitesClicked: () -> Unit,
|
||||||
onRoomSettingsClicked: (roomId: RoomId) -> Unit,
|
onRoomSettingsClicked: (roomId: RoomId) -> Unit,
|
||||||
|
onMenuActionClicked: (RoomListMenuAction) -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
|
|
@ -118,12 +120,13 @@ fun RoomListView(
|
||||||
|
|
||||||
RoomListContent(
|
RoomListContent(
|
||||||
state = state,
|
state = state,
|
||||||
|
onVerifyClicked = onVerifyClicked,
|
||||||
onRoomClicked = onRoomClicked,
|
onRoomClicked = onRoomClicked,
|
||||||
onRoomLongClicked = { onRoomLongClicked(it) },
|
onRoomLongClicked = { onRoomLongClicked(it) },
|
||||||
onOpenSettings = onSettingsClicked,
|
onOpenSettings = onSettingsClicked,
|
||||||
onVerifyClicked = onVerifyClicked,
|
|
||||||
onCreateRoomClicked = onCreateRoomClicked,
|
onCreateRoomClicked = onCreateRoomClicked,
|
||||||
onInvitesClicked = onInvitesClicked,
|
onInvitesClicked = onInvitesClicked,
|
||||||
|
onMenuActionClicked = onMenuActionClicked,
|
||||||
)
|
)
|
||||||
// This overlaid view will only be visible when state.displaySearchResults is true
|
// This overlaid view will only be visible when state.displaySearchResults is true
|
||||||
RoomListSearchResultView(
|
RoomListSearchResultView(
|
||||||
|
|
@ -143,12 +146,13 @@ fun RoomListView(
|
||||||
fun RoomListContent(
|
fun RoomListContent(
|
||||||
state: RoomListState,
|
state: RoomListState,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onVerifyClicked: () -> Unit = {},
|
onVerifyClicked: () -> Unit,
|
||||||
onRoomClicked: (RoomId) -> Unit = {},
|
onRoomClicked: (RoomId) -> Unit,
|
||||||
onRoomLongClicked: (RoomListRoomSummary) -> Unit = {},
|
onRoomLongClicked: (RoomListRoomSummary) -> Unit,
|
||||||
onOpenSettings: () -> Unit = {},
|
onOpenSettings: () -> Unit,
|
||||||
onCreateRoomClicked: () -> Unit = {},
|
onCreateRoomClicked: () -> Unit,
|
||||||
onInvitesClicked: () -> Unit = {},
|
onInvitesClicked: () -> Unit,
|
||||||
|
onMenuActionClicked: (RoomListMenuAction) -> Unit,
|
||||||
) {
|
) {
|
||||||
fun onRoomClicked(room: RoomListRoomSummary) {
|
fun onRoomClicked(room: RoomListRoomSummary) {
|
||||||
onRoomClicked(room.roomId)
|
onRoomClicked(room.roomId)
|
||||||
|
|
@ -190,6 +194,7 @@ fun RoomListContent(
|
||||||
areSearchResultsDisplayed = state.displaySearchResults,
|
areSearchResultsDisplayed = state.displaySearchResults,
|
||||||
onFilterChanged = { state.eventSink(RoomListEvents.UpdateFilter(it)) },
|
onFilterChanged = { state.eventSink(RoomListEvents.UpdateFilter(it)) },
|
||||||
onToggleSearch = { state.eventSink(RoomListEvents.ToggleSearchResults) },
|
onToggleSearch = { state.eventSink(RoomListEvents.ToggleSearchResults) },
|
||||||
|
onMenuActionClicked = onMenuActionClicked,
|
||||||
onOpenSettings = onOpenSettings,
|
onOpenSettings = onOpenSettings,
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
)
|
)
|
||||||
|
|
@ -369,7 +374,8 @@ private fun ContentToPreview(state: RoomListState) {
|
||||||
onVerifyClicked = {},
|
onVerifyClicked = {},
|
||||||
onCreateRoomClicked = {},
|
onCreateRoomClicked = {},
|
||||||
onInvitesClicked = {},
|
onInvitesClicked = {},
|
||||||
onRoomSettingsClicked = {}
|
onRoomSettingsClicked = {},
|
||||||
|
onMenuActionClicked = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.features.roomlist.impl.components
|
||||||
|
|
||||||
|
enum class RoomListMenuAction {
|
||||||
|
InviteFriends,
|
||||||
|
ReportBug
|
||||||
|
}
|
||||||
|
|
@ -19,23 +19,33 @@ package io.element.android.features.roomlist.impl.components
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.BugReport
|
||||||
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
import androidx.compose.material.icons.filled.Search
|
import androidx.compose.material.icons.filled.Search
|
||||||
|
import androidx.compose.material.icons.filled.Share
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.material3.rememberTopAppBarState
|
import androidx.compose.material3.rememberTopAppBarState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
import io.element.android.features.roomlist.impl.R
|
import io.element.android.features.roomlist.impl.R
|
||||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||||
|
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||||
import io.element.android.libraries.designsystem.theme.components.Icon
|
import io.element.android.libraries.designsystem.theme.components.Icon
|
||||||
|
|
@ -57,6 +67,7 @@ fun RoomListTopBar(
|
||||||
areSearchResultsDisplayed: Boolean,
|
areSearchResultsDisplayed: Boolean,
|
||||||
onFilterChanged: (String) -> Unit,
|
onFilterChanged: (String) -> Unit,
|
||||||
onToggleSearch: () -> Unit,
|
onToggleSearch: () -> Unit,
|
||||||
|
onMenuActionClicked: (RoomListMenuAction) -> Unit,
|
||||||
onOpenSettings: () -> Unit,
|
onOpenSettings: () -> Unit,
|
||||||
scrollBehavior: TopAppBarScrollBehavior,
|
scrollBehavior: TopAppBarScrollBehavior,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
|
@ -79,6 +90,7 @@ fun RoomListTopBar(
|
||||||
matrixUser = matrixUser,
|
matrixUser = matrixUser,
|
||||||
onOpenSettings = onOpenSettings,
|
onOpenSettings = onOpenSettings,
|
||||||
onSearchClicked = onToggleSearch,
|
onSearchClicked = onToggleSearch,
|
||||||
|
onMenuActionClicked = onMenuActionClicked,
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
|
|
@ -90,15 +102,19 @@ private fun DefaultRoomListTopBar(
|
||||||
matrixUser: MatrixUser?,
|
matrixUser: MatrixUser?,
|
||||||
scrollBehavior: TopAppBarScrollBehavior,
|
scrollBehavior: TopAppBarScrollBehavior,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onOpenSettings: () -> Unit = {},
|
onOpenSettings: () -> Unit,
|
||||||
onSearchClicked: () -> Unit = {},
|
onSearchClicked: () -> Unit,
|
||||||
|
onMenuActionClicked: (RoomListMenuAction) -> Unit,
|
||||||
) {
|
) {
|
||||||
|
var showMenu by remember { mutableStateOf(false) }
|
||||||
MediumTopAppBar(
|
MediumTopAppBar(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.nestedScroll(scrollBehavior.nestedScrollConnection),
|
.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
title = {
|
title = {
|
||||||
|
val fontSize = if (scrollBehavior.state.collapsedFraction > 0.5) 20.sp else 22.sp
|
||||||
Text(
|
Text(
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
|
style = MaterialTheme.typography.headlineMedium.copy(fontSize = fontSize),
|
||||||
text = stringResource(id = R.string.screen_roomlist_main_space_title)
|
text = stringResource(id = R.string.screen_roomlist_main_space_title)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
@ -108,7 +124,11 @@ private fun DefaultRoomListTopBar(
|
||||||
modifier = Modifier.testTag(TestTags.homeScreenSettings),
|
modifier = Modifier.testTag(TestTags.homeScreenSettings),
|
||||||
onClick = onOpenSettings
|
onClick = onOpenSettings
|
||||||
) {
|
) {
|
||||||
val avatarData by remember { derivedStateOf { matrixUser.getAvatarData() } }
|
val avatarData by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
matrixUser.getAvatarData(size = AvatarSize.Custom(28.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
Avatar(avatarData, contentDescription = stringResource(CommonStrings.common_settings))
|
Avatar(avatarData, contentDescription = stringResource(CommonStrings.common_settings))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -119,6 +139,32 @@ private fun DefaultRoomListTopBar(
|
||||||
) {
|
) {
|
||||||
Icon(Icons.Default.Search, contentDescription = stringResource(CommonStrings.action_search))
|
Icon(Icons.Default.Search, contentDescription = stringResource(CommonStrings.action_search))
|
||||||
}
|
}
|
||||||
|
IconButton(
|
||||||
|
onClick = { showMenu = !showMenu }
|
||||||
|
) {
|
||||||
|
Icon(Icons.Default.MoreVert, contentDescription = null)
|
||||||
|
}
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = showMenu,
|
||||||
|
onDismissRequest = { showMenu = false }
|
||||||
|
) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
onClick = {
|
||||||
|
showMenu = false
|
||||||
|
onMenuActionClicked(RoomListMenuAction.InviteFriends)
|
||||||
|
},
|
||||||
|
text = { Text(stringResource(id = CommonStrings.action_invite)) },
|
||||||
|
leadingIcon = { Icon(Icons.Default.Share, contentDescription = null) }
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
onClick = {
|
||||||
|
showMenu = false
|
||||||
|
onMenuActionClicked(RoomListMenuAction.ReportBug)
|
||||||
|
},
|
||||||
|
text = { Text(stringResource(id = CommonStrings.common_report_a_bug)) },
|
||||||
|
leadingIcon = { Icon(Icons.Default.BugReport, contentDescription = null) }
|
||||||
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
windowInsets = WindowInsets(0.dp),
|
windowInsets = WindowInsets(0.dp),
|
||||||
|
|
@ -139,5 +185,8 @@ private fun DefaultRoomListTopBarPreview() {
|
||||||
DefaultRoomListTopBar(
|
DefaultRoomListTopBar(
|
||||||
matrixUser = MatrixUser(UserId("@id:domain"), "Alice"),
|
matrixUser = MatrixUser(UserId("@id:domain"), "Alice"),
|
||||||
scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState()),
|
scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState()),
|
||||||
|
onOpenSettings = {},
|
||||||
|
onSearchClicked = {},
|
||||||
|
onMenuActionClicked = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,12 @@ dependencies {
|
||||||
implementation(projects.libraries.di)
|
implementation(projects.libraries.di)
|
||||||
implementation(libs.dagger)
|
implementation(libs.dagger)
|
||||||
implementation(libs.androidx.corektx)
|
implementation(libs.androidx.corektx)
|
||||||
|
implementation(projects.libraries.core)
|
||||||
implementation(projects.libraries.matrix.api)
|
implementation(projects.libraries.matrix.api)
|
||||||
|
implementation(projects.libraries.androidutils)
|
||||||
implementation(projects.libraries.architecture)
|
implementation(projects.libraries.architecture)
|
||||||
|
implementation(projects.libraries.uiStrings)
|
||||||
|
implementation(projects.services.toolbox.api)
|
||||||
|
|
||||||
testImplementation(libs.test.junit)
|
testImplementation(libs.test.junit)
|
||||||
testImplementation(libs.test.truth)
|
testImplementation(libs.test.truth)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.element.android.libraries.deeplink.usecase
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import io.element.android.libraries.androidutils.system.startSharePlainTextIntent
|
||||||
|
import io.element.android.libraries.core.meta.BuildMeta
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import io.element.android.libraries.matrix.api.permalink.PermalinkBuilder
|
||||||
|
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
import io.element.android.libraries.androidutils.R as AndroidUtilsR
|
||||||
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
|
class InviteFriendsUseCase @Inject constructor(
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
|
private val matrixClient: MatrixClient,
|
||||||
|
private val buildMeta: BuildMeta,
|
||||||
|
) {
|
||||||
|
fun execute(activity: Activity) {
|
||||||
|
val permalinkResult = PermalinkBuilder.permalinkForUser(matrixClient.sessionId)
|
||||||
|
permalinkResult.fold(
|
||||||
|
onSuccess = { permalink ->
|
||||||
|
val appName = buildMeta.applicationName
|
||||||
|
startSharePlainTextIntent(
|
||||||
|
context = activity,
|
||||||
|
activityResultLauncher = null,
|
||||||
|
chooserTitle = stringProvider.getString(CommonStrings.action_invite_friends),
|
||||||
|
text = stringProvider.getString(CommonStrings.invite_friends_text, appName, permalink),
|
||||||
|
extraTitle = stringProvider.getString(CommonStrings.invite_friends_rich_title, appName),
|
||||||
|
noActivityFoundMessage = stringProvider.getString(AndroidUtilsR.string.error_no_compatible_app_found)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onFailure = {
|
||||||
|
Timber.e(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -103,6 +103,7 @@ class RoomListScreen(
|
||||||
onCreateRoomClicked = {},
|
onCreateRoomClicked = {},
|
||||||
onInvitesClicked = {},
|
onInvitesClicked = {},
|
||||||
onRoomSettingsClicked = {},
|
onRoomSettingsClicked = {},
|
||||||
|
onMenuActionClicked = {},
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue