diff --git a/app/src/main/java/chat/revolt/composables/screens/chat/drawer/ChannelSideDrawer.kt b/app/src/main/java/chat/revolt/composables/screens/chat/drawer/ChannelSideDrawer.kt index c78fb7c4..8b49162c 100644 --- a/app/src/main/java/chat/revolt/composables/screens/chat/drawer/ChannelSideDrawer.kt +++ b/app/src/main/java/chat/revolt/composables/screens/chat/drawer/ChannelSideDrawer.kt @@ -37,7 +37,6 @@ import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CornerSize -import androidx.compose.material3.DrawerState import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Icon @@ -99,7 +98,6 @@ import chat.revolt.composables.screens.chat.ChannelIcon import chat.revolt.screens.chat.ChatRouterDestination import chat.revolt.screens.chat.LocalIsConnected import chat.revolt.sheets.ChannelContextSheet -import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class) @Composable @@ -108,7 +106,6 @@ fun ChannelSideDrawer( currentDestination: ChatRouterDestination, onDestinationChanged: (ChatRouterDestination) -> Unit, onLongPressAvatar: () -> Unit, - drawerState: DrawerState?, navigateToServer: (String) -> Unit, onShowServerContextSheet: (String) -> Unit, showSettingsIcon: Boolean, @@ -126,6 +123,7 @@ fun ChannelSideDrawer( LaunchedEffect(currentDestination) { if (currentDestination is ChatRouterDestination.Channel && currentServer != null) { val channelIndex = categorisedChannels?.indexOfFirst { + when (it) { is CategorisedChannelList.Channel -> it.channel.id == currentDestination.channelId else -> false @@ -357,9 +355,6 @@ fun ChannelSideDrawer( .clip(CircleShape) .clickable { serverInList.id?.let { srvId -> navigateToServer(srvId) } - scope.launch { - drawerState?.close() - } }) { val icon = serverInList.icon?.id?.let { iconId -> "$REVOLT_FILES/icons/$iconId" @@ -439,9 +434,6 @@ fun ChannelSideDrawer( .clip(CircleShape) .clickable { onOpenSettings() - scope.launch { - drawerState?.close() - } } .size(48.dp), contentAlignment = Alignment.Center @@ -577,7 +569,6 @@ fun ChannelSideDrawer( DirectMessagesChannelListRenderer( currentDestination, onDestinationChanged, - drawerState, channelListState, onOpenChannelContextSheet = { channelContextSheetTarget = it } ) @@ -586,7 +577,6 @@ fun ChannelSideDrawer( categorisedChannels, currentDestination, onDestinationChanged, - drawerState, channelListState, onOpenChannelContextSheet = { channelContextSheetTarget = it }, serverId = currentServer @@ -600,11 +590,9 @@ fun ChannelSideDrawer( fun ColumnScope.DirectMessagesChannelListRenderer( currentDestination: ChatRouterDestination, onDestinationChanged: (ChatRouterDestination) -> Unit, - drawerState: DrawerState?, channelListState: LazyListState, onOpenChannelContextSheet: (String) -> Unit, ) { - val scope = rememberCoroutineScope() val dmAbleChannels = RevoltAPI.channelCache.values .filter { it.channelType == ChannelType.DirectMessage || it.channelType == ChannelType.Group } @@ -629,9 +617,6 @@ fun ColumnScope.DirectMessagesChannelListRenderer( isCurrent = currentDestination is ChatRouterDestination.Overview, onDestinationChanged = { onDestinationChanged(ChatRouterDestination.Overview) - scope.launch { - drawerState?.close() - } }, hasUnread = false, onOpenChannelContextSheet = {} @@ -650,9 +635,6 @@ fun ColumnScope.DirectMessagesChannelListRenderer( isCurrent = currentDestination is ChatRouterDestination.Friends, onDestinationChanged = { onDestinationChanged(ChatRouterDestination.Friends) - scope.launch { - drawerState?.close() - } }, hasUnread = FriendRequests.getIncoming().isNotEmpty(), onOpenChannelContextSheet = {}, @@ -675,9 +657,6 @@ fun ColumnScope.DirectMessagesChannelListRenderer( currentDestination.channelId == notesChannel.id, onDestinationChanged = { onDestinationChanged(it) - scope.launch { - drawerState?.close() - } }, hasUnread = false, onOpenChannelContextSheet = {}, @@ -732,9 +711,6 @@ fun ColumnScope.DirectMessagesChannelListRenderer( isMuted = NotificationSettingsProvider.isChannelMuted(channel.id!!, null), onDestinationChanged = { dest -> onDestinationChanged(dest) - scope.launch { - drawerState?.close() - } }, onOpenChannelContextSheet = onOpenChannelContextSheet ) @@ -756,13 +732,10 @@ fun ColumnScope.ServerChannelListRenderer( categorisedChannels: List?, currentDestination: ChatRouterDestination, onDestinationChanged: (ChatRouterDestination) -> Unit, - drawerState: DrawerState?, channelListState: LazyListState, onOpenChannelContextSheet: (String) -> Unit, serverId: String ) { - val scope = rememberCoroutineScope() - LazyColumn( state = channelListState, verticalArrangement = Arrangement.spacedBy(4.dp), @@ -806,11 +779,8 @@ fun ColumnScope.ServerChannelListRenderer( else -> false }, - onDestinationChanged = { - onDestinationChanged(it) - scope.launch { - drawerState?.close() - } + onDestinationChanged = { dest -> + onDestinationChanged(dest) }, hasUnread = channelOrCat.channel.lastMessageID?.let { lastMessageID -> RevoltAPI.unreads.hasUnread( diff --git a/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt b/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt index 0489ba8d..8ba4d391 100644 --- a/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt +++ b/app/src/main/java/chat/revolt/screens/chat/ChatRouterScreen.kt @@ -1,19 +1,15 @@ package chat.revolt.screens.chat +import android.Manifest import android.annotation.SuppressLint import android.content.Context import android.os.Build import android.util.Log import android.view.accessibility.AccessibilityManager import android.view.inputmethod.InputMethodManager -import androidx.activity.compose.BackHandler import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.WindowInsets @@ -23,15 +19,20 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.systemBars import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Face +import androidx.compose.material.icons.filled.Home +import androidx.compose.material.icons.filled.Person import androidx.compose.material3.AlertDialog -import androidx.compose.material3.DismissibleDrawerSheet -import androidx.compose.material3.DismissibleNavigationDrawer +import androidx.compose.material3.BottomAppBar import androidx.compose.material3.DrawerState import androidx.compose.material3.DrawerValue import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.rememberDrawerState @@ -52,8 +53,6 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.snapshotFlow import androidx.compose.runtime.structuralEqualityPolicy import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.painterResource @@ -79,7 +78,6 @@ import chat.revolt.composables.chat.DisconnectedNotice import chat.revolt.composables.screens.chat.drawer.ChannelSideDrawer import chat.revolt.dialogs.NotificationRationaleDialog import chat.revolt.internals.Changelogs -import chat.revolt.internals.extensions.zero import chat.revolt.persistence.KVStorage import chat.revolt.screens.chat.dialogs.safety.ReportMessageDialog import chat.revolt.screens.chat.dialogs.safety.ReportServerDialog @@ -111,6 +109,7 @@ import javax.inject.Inject sealed class ChatRouterDestination { data object Overview : ChatRouterDestination() data object Friends : ChatRouterDestination() + data object Home : ChatRouterDestination() data class Channel(val channelId: String) : ChatRouterDestination() data class NoCurrentChannel(val serverId: String?) : ChatRouterDestination() @@ -120,6 +119,7 @@ sealed class ChatRouterDestination { is Friends -> "friends" is Channel -> "channel/$channelId" is NoCurrentChannel -> "no_current_channel/$serverId" + ChatRouterDestination.Home -> "home" } } @@ -274,7 +274,6 @@ val LocalIsConnected = compositionLocalOf(structuralEqualityPolicy()) { false } fun ChatRouterScreen( topNav: NavController, windowSizeClass: WindowSizeClass, - disableBackHandler: Boolean, onNullifiedUser: () -> Unit, onEnterVoiceUI: (String) -> Unit, viewModel: ChatRouterViewModel = hiltViewModel() @@ -284,8 +283,6 @@ fun ChatRouterScreen( val context = LocalContext.current val view = LocalView.current - var drawerWidth by remember { mutableFloatStateOf(0.0f) } - var showPlatformModDMHint by remember { mutableStateOf(false) } var showStatusSheet by remember { mutableStateOf(false) } @@ -736,7 +733,7 @@ fun ChatRouterScreen( onSelected = { accepted -> if (accepted) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - askNotificationsPermission.launch(android.Manifest.permission.POST_NOTIFICATIONS) + askNotificationsPermission.launch(Manifest.permission.POST_NOTIFICATIONS) } else { viewModel.setRegisterForNotifications() } @@ -817,128 +814,26 @@ fun ChatRouterScreen( CompositionLocalProvider( LocalIsConnected provides (RealtimeSocket.disconnectionState == DisconnectionState.Connected) ) { - if (useTabletAwareUI) { - Row { - DismissibleDrawerSheet( - drawerContainerColor = Color.Transparent, - windowInsets = WindowInsets.zero - ) { - Sidebar( - viewModel = viewModel, - topNav = topNav, - currentServer = currentServer, - onShowStatusSheet = { + ChannelNavigator( + dest = viewModel.currentDestination, + topNav = topNav, + toggleDrawer = { + toggleDrawerLambda() + }, + onShowStatusSheet = { showStatusSheet = true - }, - onShowServerContextSheet = { + }, + onShowServerContextSheet = { serverContextSheetTarget = it showServerContextSheet = true - }, - onShowAddServerSheet = { + }, + onShowAddServerSheet = { showAddServerSheet = true - }, - showSettingsButton = isTouchExplorationEnabled, - onOpenSettings = { - topNav.navigate("settings") - }, - ) - } - ChannelNavigator( - dest = viewModel.currentDestination, - topNav = topNav, - useDrawer = false, - disableBackHandler = disableBackHandler, - toggleDrawer = { - toggleDrawerLambda() - }, - onEnterVoiceUI = onEnterVoiceUI, - ) - } - } else { - var useSidebarGesture by remember { mutableStateOf(true) } - DismissibleNavigationDrawer( - drawerState = drawerState, - gesturesEnabled = useSidebarGesture, - drawerContent = { - DismissibleDrawerSheet( - drawerContainerColor = Color.Transparent, - windowInsets = WindowInsets.zero, - modifier = Modifier.onSizeChanged { - drawerWidth = it.width.toFloat() - } - ) { - Sidebar( - viewModel = viewModel, - topNav = topNav, - currentServer = currentServer, - onShowStatusSheet = { - showStatusSheet = true - }, - onShowServerContextSheet = { - serverContextSheetTarget = it - showServerContextSheet = true - }, - onShowAddServerSheet = { - showAddServerSheet = true - }, - showSettingsButton = isTouchExplorationEnabled, - onOpenSettings = { - topNav.navigate("settings") - }, - drawerState = drawerState - ) - } - }, - content = { - Box(Modifier.fillMaxSize()) { - ChannelNavigator( - dest = viewModel.currentDestination, - topNav = topNav, - useDrawer = true, - disableBackHandler = disableBackHandler, - toggleDrawer = { - toggleDrawerLambda() - }, - drawerState = drawerState, - drawerGestureEnabled = useSidebarGesture, - setDrawerGestureEnabled = { - useSidebarGesture = it - }, - onEnterVoiceUI = onEnterVoiceUI, - ) - - // This is the overlay on the main content when the drawer is open - val interactionSource = remember { MutableInteractionSource() } - Box( - Modifier - .then( - if (drawerState.isOpen) { - Modifier.clickable( - interactionSource = interactionSource, - indication = null, - enabled = drawerState.isOpen, - onClick = { - scope.launch { - drawerState.close() - } - } - ) - } else Modifier - ) - .fillMaxSize() - .background( - MaterialTheme - .colorScheme - .surfaceContainerLowest - .copy( - alpha = (1.0f + (drawerState.currentOffset / drawerWidth)) * 0.7f - ) - ) - ) - } - } - ) - } + }, + isTouchExplorationEnabled = isTouchExplorationEnabled, + viewModel = viewModel, + currentServer = currentServer, + ) } } } @@ -948,7 +843,6 @@ fun Sidebar( viewModel: ChatRouterViewModel, currentServer: String?, topNav: NavController, - drawerState: DrawerState? = null, onShowStatusSheet: () -> Unit, onShowServerContextSheet: (String) -> Unit, onShowAddServerSheet: () -> Unit, @@ -959,7 +853,6 @@ fun Sidebar( onDestinationChanged = viewModel::setSaveDestination, currentDestination = viewModel.currentDestination, currentServer = currentServer, - drawerState = drawerState, navigateToServer = viewModel::navigateToServer, onLongPressAvatar = onShowStatusSheet, onShowServerContextSheet = onShowServerContextSheet, @@ -974,59 +867,126 @@ fun Sidebar( fun ChannelNavigator( dest: ChatRouterDestination, topNav: NavController, - useDrawer: Boolean, + viewModel: ChatRouterViewModel, + onShowStatusSheet: () -> Unit = {}, + onShowAddServerSheet: () -> Unit = {}, + onShowServerContextSheet: (String) -> Unit = {}, + currentServer: String?, toggleDrawer: () -> Unit, + isTouchExplorationEnabled: Boolean, drawerState: DrawerState? = null, - drawerGestureEnabled: Boolean = true, - disableBackHandler: Boolean = false, - onEnterVoiceUI: (String) -> Unit = {}, setDrawerGestureEnabled: (Boolean) -> Unit = {}, ) { val scope = rememberCoroutineScope() - BackHandler(useDrawer && !disableBackHandler) { - toggleDrawer() - } - - Column(Modifier.fillMaxSize()) { - when (dest) { - is ChatRouterDestination.Overview -> { - OverviewScreen( - navController = topNav, - useDrawer = useDrawer, - onDrawerClicked = toggleDrawer, - ) - } - - is ChatRouterDestination.Friends -> { - FriendsScreen( - topNav = topNav, - useDrawer = useDrawer, - onDrawerClicked = toggleDrawer, - ) - } - - is ChatRouterDestination.Channel -> { - ChannelScreen( - channelId = dest.channelId, - onToggleDrawer = { - scope.launch { - if (drawerState?.isOpen == true) { - drawerState.close() - } else { - drawerState?.open() - } - } + Scaffold( + modifier = Modifier.fillMaxSize(), + bottomBar = { + BottomAppBar { + NavigationBarItem( + icon = { + Icon( + imageVector = Icons.Default.Home, + contentDescription = "Home", + ) }, - useDrawer = useDrawer, - drawerGestureEnabled = drawerGestureEnabled, - setDrawerGestureEnabled = setDrawerGestureEnabled, - drawerIsOpen = drawerState?.isOpen == true, + label = { + Text(text = "you") + }, + selected = dest is ChatRouterDestination.Home, + enabled = true, + onClick = { + viewModel.setSaveDestination(ChatRouterDestination.Home) + } + ) + NavigationBarItem( + icon = { + Icon( + imageVector = Icons.Default.Person, + contentDescription = "Friends", + ) + }, + label = { + Text(text = "Friends") + }, + selected = dest is ChatRouterDestination.Friends, + enabled = true, + onClick = { + viewModel.setSaveDestination(ChatRouterDestination.Friends) + } + ) + NavigationBarItem( + icon = { + Icon( + imageVector = Icons.Default.Face, + contentDescription = "You", + ) + }, + label = { + Text(text = "you") + }, + selected = dest is ChatRouterDestination.Overview, + enabled = true, + onClick = { + viewModel.setSaveDestination(ChatRouterDestination.Overview) + } ) } + } + ) { innerPadding -> + Column { + when (dest) { + is ChatRouterDestination.Overview -> { + OverviewScreen( + navController = topNav, + onDrawerClicked = toggleDrawer, + ) + } - is ChatRouterDestination.NoCurrentChannel -> { - NoCurrentChannelScreen(useDrawer = useDrawer, onDrawerClicked = toggleDrawer) + is ChatRouterDestination.Friends -> { + FriendsScreen( + topNav = topNav, + onDrawerClicked = toggleDrawer, + ) + } + + is ChatRouterDestination.Home -> { + Row { + Sidebar( + viewModel = viewModel, + topNav = topNav, + currentServer = currentServer, + onShowStatusSheet = onShowStatusSheet, + onShowServerContextSheet = onShowServerContextSheet, + onShowAddServerSheet = onShowAddServerSheet, + showSettingsButton = isTouchExplorationEnabled, + onOpenSettings = { + topNav.navigate("settings") + }, + ) + } + } + + is ChatRouterDestination.Channel -> { + ChannelScreen( + channelId = dest.channelId, + onToggleDrawer = { + scope.launch { + if (drawerState?.isOpen == true) { + drawerState.close() + } else { + drawerState?.open() + } + } + }, + setDrawerGestureEnabled = setDrawerGestureEnabled, + drawerIsOpen = drawerState?.isOpen == true, + ) + } + + is ChatRouterDestination.NoCurrentChannel -> { + NoCurrentChannelScreen(onDrawerClicked = toggleDrawer) + } } } } diff --git a/app/src/main/java/chat/revolt/screens/chat/views/FriendsScreen.kt b/app/src/main/java/chat/revolt/screens/chat/views/FriendsScreen.kt index 38e54d16..5906c657 100644 --- a/app/src/main/java/chat/revolt/screens/chat/views/FriendsScreen.kt +++ b/app/src/main/java/chat/revolt/screens/chat/views/FriendsScreen.kt @@ -120,7 +120,7 @@ private fun showInvalidClipboardToast(context: Context) { ExperimentalMaterial3ExpressiveApi::class ) @Composable -fun FriendsScreen(topNav: NavController, useDrawer: Boolean, onDrawerClicked: () -> Unit) { +fun FriendsScreen(topNav: NavController, useDrawer: Boolean = false, onDrawerClicked: () -> Unit) { val clipboard = LocalClipboard.current val context = LocalContext.current var overflowMenuShown by remember { mutableStateOf(false) } diff --git a/app/src/main/java/chat/revolt/screens/chat/views/NoCurrentChannelScreen.kt b/app/src/main/java/chat/revolt/screens/chat/views/NoCurrentChannelScreen.kt index 5354c8a8..91dcc03e 100644 --- a/app/src/main/java/chat/revolt/screens/chat/views/NoCurrentChannelScreen.kt +++ b/app/src/main/java/chat/revolt/screens/chat/views/NoCurrentChannelScreen.kt @@ -10,8 +10,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBars -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Menu import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -33,7 +31,7 @@ import chat.revolt.screens.chat.LocalIsConnected @OptIn(ExperimentalMaterial3Api::class) @Composable -fun NoCurrentChannelScreen(useDrawer: Boolean, onDrawerClicked: () -> Unit) { +fun NoCurrentChannelScreen(useDrawer: Boolean = false, onDrawerClicked: () -> Unit) { Scaffold( topBar = { Column { diff --git a/app/src/main/java/chat/revolt/screens/chat/views/OverviewScreen.kt b/app/src/main/java/chat/revolt/screens/chat/views/OverviewScreen.kt index 31622127..fa9bc235 100644 --- a/app/src/main/java/chat/revolt/screens/chat/views/OverviewScreen.kt +++ b/app/src/main/java/chat/revolt/screens/chat/views/OverviewScreen.kt @@ -68,7 +68,7 @@ import io.sentry.Sentry @Composable fun OverviewScreen( navController: NavController, - useDrawer: Boolean, + useDrawer: Boolean = false, onDrawerClicked: () -> Unit, includePadding: Boolean = true ) { diff --git a/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreen.kt b/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreen.kt index 5c8b80ab..6e73fe4e 100644 --- a/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreen.kt +++ b/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreen.kt @@ -190,9 +190,8 @@ private const val NOT_ENOUGH_SPACE_FOR_PANES_THRESHOLD = 500 fun ChannelScreen( channelId: String, onToggleDrawer: () -> Unit, - useDrawer: Boolean, + useDrawer: Boolean = false, useBackButton: Boolean = false, - drawerGestureEnabled: Boolean = true, setDrawerGestureEnabled: (Boolean) -> Unit = {}, drawerIsOpen: Boolean = false, backButtonAction: (() -> Unit)? = null, @@ -347,7 +346,7 @@ fun ChannelScreen( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues ) - } catch (e: Exception) { + } catch (_: Exception) { Toast.makeText( context, context.getString( @@ -363,7 +362,7 @@ fun ChannelScreen( capturedPhotoUri.value?.let { uri -> pickCameraLauncher.launch(uri) } - } catch (e: Exception) { + } catch (_: Exception) { Toast.makeText( context, context.getString(