TwoPane display for chats in tablets and folds.
This commit is contained in:
@@ -102,9 +102,15 @@ dependencies {
|
|||||||
// Observe Live data as State
|
// Observe Live data as State
|
||||||
implementation "androidx.compose.runtime:runtime-livedata:$compose_ui_version"
|
implementation "androidx.compose.runtime:runtime-livedata:$compose_ui_version"
|
||||||
|
|
||||||
|
// Material 3 Design
|
||||||
implementation "androidx.compose.material3:material3:${material3_version}"
|
implementation "androidx.compose.material3:material3:${material3_version}"
|
||||||
implementation "androidx.compose.material:material-icons-extended:$compose_ui_version"
|
implementation "androidx.compose.material:material-icons-extended:$compose_ui_version"
|
||||||
|
|
||||||
|
// Adaptive Layout / Two Pane
|
||||||
|
implementation "androidx.compose.material3:material3-window-size-class:${material3_version}"
|
||||||
|
implementation "com.google.accompanist:accompanist-adaptive:0.33.2-alpha"
|
||||||
|
|
||||||
|
|
||||||
// Lifecycle
|
// Lifecycle
|
||||||
implementation "androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version"
|
implementation "androidx.lifecycle:lifecycle-runtime-compose:$lifecycle_version"
|
||||||
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
|
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycle_version"
|
||||||
|
|||||||
@@ -16,10 +16,13 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
|
||||||
|
import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.google.accompanist.adaptive.calculateDisplayFeatures
|
||||||
import com.vitorpamplona.amethyst.LocalPreferences
|
import com.vitorpamplona.amethyst.LocalPreferences
|
||||||
import com.vitorpamplona.amethyst.ServiceManager
|
import com.vitorpamplona.amethyst.ServiceManager
|
||||||
import com.vitorpamplona.amethyst.service.ExternalSignerUtils
|
import com.vitorpamplona.amethyst.service.ExternalSignerUtils
|
||||||
@@ -51,6 +54,7 @@ import java.nio.charset.StandardCharsets
|
|||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
private val isOnMobileDataState = mutableStateOf(false)
|
private val isOnMobileDataState = mutableStateOf(false)
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
|
||||||
@RequiresApi(Build.VERSION_CODES.R)
|
@RequiresApi(Build.VERSION_CODES.R)
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
ExternalSignerUtils.start(this)
|
ExternalSignerUtils.start(this)
|
||||||
@@ -60,9 +64,16 @@ class MainActivity : AppCompatActivity() {
|
|||||||
setContent {
|
setContent {
|
||||||
val sharedPreferencesViewModel: SharedPreferencesViewModel = viewModel()
|
val sharedPreferencesViewModel: SharedPreferencesViewModel = viewModel()
|
||||||
|
|
||||||
LaunchedEffect(key1 = sharedPreferencesViewModel, isOnMobileDataState) {
|
val displayFeatures = calculateDisplayFeatures(this)
|
||||||
|
val windowSizeClass = calculateWindowSizeClass(this)
|
||||||
|
|
||||||
|
LaunchedEffect(key1 = sharedPreferencesViewModel) {
|
||||||
sharedPreferencesViewModel.init()
|
sharedPreferencesViewModel.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(isOnMobileDataState) {
|
||||||
sharedPreferencesViewModel.updateConnectivityStatusState(isOnMobileDataState)
|
sharedPreferencesViewModel.updateConnectivityStatusState(isOnMobileDataState)
|
||||||
|
sharedPreferencesViewModel.updateDisplaySettings(windowSizeClass, displayFeatures)
|
||||||
}
|
}
|
||||||
|
|
||||||
AmethystTheme(sharedPreferencesViewModel) {
|
AmethystTheme(sharedPreferencesViewModel) {
|
||||||
|
|||||||
@@ -238,7 +238,9 @@ private fun ChannelTitleWithLabelInfo(channelName: String, modifier: Modifier) {
|
|||||||
text = channelNameAndBoostInfo,
|
text = channelNameAndBoostInfo,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
style = LocalTextStyle.current.copy(textDirection = TextDirection.Content)
|
style = LocalTextStyle.current.copy(textDirection = TextDirection.Content),
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.vitorpamplona.amethyst.ui.screen
|
package com.vitorpamplona.amethyst.ui.screen
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
import androidx.compose.material3.windowsizeclass.WindowSizeClass
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
@@ -10,6 +11,7 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.core.os.LocaleListCompat
|
import androidx.core.os.LocaleListCompat
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.window.layout.DisplayFeature
|
||||||
import com.vitorpamplona.amethyst.LocalPreferences
|
import com.vitorpamplona.amethyst.LocalPreferences
|
||||||
import com.vitorpamplona.amethyst.model.BooleanType
|
import com.vitorpamplona.amethyst.model.BooleanType
|
||||||
import com.vitorpamplona.amethyst.model.ConnectivityType
|
import com.vitorpamplona.amethyst.model.ConnectivityType
|
||||||
@@ -31,6 +33,9 @@ class SettingsState() {
|
|||||||
|
|
||||||
var isOnMobileData: State<Boolean> = mutableStateOf(false)
|
var isOnMobileData: State<Boolean> = mutableStateOf(false)
|
||||||
|
|
||||||
|
var windowSizeClass = mutableStateOf<WindowSizeClass?>(null)
|
||||||
|
var displayFeatures = mutableStateOf<List<DisplayFeature>>(emptyList())
|
||||||
|
|
||||||
val showProfilePictures = derivedStateOf {
|
val showProfilePictures = derivedStateOf {
|
||||||
when (automaticallyShowProfilePictures) {
|
when (automaticallyShowProfilePictures) {
|
||||||
ConnectivityType.WIFI_ONLY -> !isOnMobileData.value
|
ConnectivityType.WIFI_ONLY -> !isOnMobileData.value
|
||||||
@@ -151,6 +156,15 @@ class SharedPreferencesViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateDisplaySettings(windowSizeClass: WindowSizeClass, displayFeatures: List<DisplayFeature>) {
|
||||||
|
if (sharedPrefs.windowSizeClass.value != windowSizeClass) {
|
||||||
|
sharedPrefs.windowSizeClass.value = windowSizeClass
|
||||||
|
}
|
||||||
|
if (sharedPrefs.displayFeatures.value != displayFeatures) {
|
||||||
|
sharedPrefs.displayFeatures.value = displayFeatures
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun saveSharedSettings() {
|
fun saveSharedSettings() {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
LocalPreferences.saveSharedSettings(
|
LocalPreferences.saveSharedSettings(
|
||||||
|
|||||||
+133
-2
@@ -8,10 +8,12 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
|
import androidx.compose.material3.Divider
|
||||||
import androidx.compose.material3.DropdownMenu
|
import androidx.compose.material3.DropdownMenu
|
||||||
import androidx.compose.material3.DropdownMenuItem
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
@@ -20,6 +22,8 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.Tab
|
import androidx.compose.material3.Tab
|
||||||
import androidx.compose.material3.TabRow
|
import androidx.compose.material3.TabRow
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
|
||||||
|
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
@@ -38,24 +42,152 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.LifecycleEventObserver
|
import androidx.lifecycle.LifecycleEventObserver
|
||||||
|
import com.google.accompanist.adaptive.FoldAwareConfiguration
|
||||||
|
import com.google.accompanist.adaptive.HorizontalTwoPaneStrategy
|
||||||
|
import com.google.accompanist.adaptive.TwoPane
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource
|
import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource
|
||||||
|
import com.vitorpamplona.amethyst.ui.buttons.ChannelFabColumn
|
||||||
import com.vitorpamplona.amethyst.ui.screen.ChatroomListFeedView
|
import com.vitorpamplona.amethyst.ui.screen.ChatroomListFeedView
|
||||||
import com.vitorpamplona.amethyst.ui.screen.FeedViewModel
|
import com.vitorpamplona.amethyst.ui.screen.FeedViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListKnownFeedViewModel
|
import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListKnownFeedViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListNewFeedViewModel
|
import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListNewFeedViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Size20dp
|
||||||
import com.vitorpamplona.amethyst.ui.theme.TabRowHeight
|
import com.vitorpamplona.amethyst.ui.theme.TabRowHeight
|
||||||
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
import com.vitorpamplona.amethyst.ui.theme.placeholderText
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ChatroomListScreen(
|
fun ChatroomListScreen(
|
||||||
knownFeedViewModel: NostrChatroomListKnownFeedViewModel,
|
knownFeedViewModel: NostrChatroomListKnownFeedViewModel,
|
||||||
newFeedViewModel: NostrChatroomListNewFeedViewModel,
|
newFeedViewModel: NostrChatroomListNewFeedViewModel,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit
|
nav: (String) -> Unit
|
||||||
|
) {
|
||||||
|
val windowSizeClass = accountViewModel.settings.windowSizeClass.value
|
||||||
|
|
||||||
|
val twoPane by remember {
|
||||||
|
derivedStateOf {
|
||||||
|
when (windowSizeClass?.widthSizeClass) {
|
||||||
|
WindowWidthSizeClass.Compact -> false
|
||||||
|
WindowWidthSizeClass.Expanded, WindowWidthSizeClass.Medium -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (twoPane && windowSizeClass != null) {
|
||||||
|
ChatroomListTwoPane(
|
||||||
|
knownFeedViewModel = knownFeedViewModel,
|
||||||
|
newFeedViewModel = newFeedViewModel,
|
||||||
|
widthSizeClass = windowSizeClass.widthSizeClass,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
ChatroomListScreenOnlyList(
|
||||||
|
knownFeedViewModel = knownFeedViewModel,
|
||||||
|
newFeedViewModel = newFeedViewModel,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class RouteId(val route: String, val id: String)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ChatroomListTwoPane(
|
||||||
|
knownFeedViewModel: NostrChatroomListKnownFeedViewModel,
|
||||||
|
newFeedViewModel: NostrChatroomListNewFeedViewModel,
|
||||||
|
widthSizeClass: WindowWidthSizeClass,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: (String) -> Unit
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* The index of the currently selected word, or `null` if none is selected
|
||||||
|
*/
|
||||||
|
var selectedRoute: RouteId? by remember { mutableStateOf(null) }
|
||||||
|
|
||||||
|
val navInterceptor = remember {
|
||||||
|
{ fullRoute: String ->
|
||||||
|
if (fullRoute.startsWith("Room/") || fullRoute.startsWith("Channel/")) {
|
||||||
|
val route = fullRoute.substringBefore("/")
|
||||||
|
val id = fullRoute.substringAfter("/")
|
||||||
|
selectedRoute = RouteId(route, id)
|
||||||
|
} else {
|
||||||
|
nav(fullRoute)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val strategy = remember {
|
||||||
|
if (widthSizeClass == WindowWidthSizeClass.Expanded) {
|
||||||
|
HorizontalTwoPaneStrategy(
|
||||||
|
splitFraction = 1f / 3f
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
HorizontalTwoPaneStrategy(
|
||||||
|
splitFraction = 1f / 2.5f
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TwoPane(
|
||||||
|
first = {
|
||||||
|
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.BottomEnd) {
|
||||||
|
ChatroomListScreenOnlyList(
|
||||||
|
knownFeedViewModel,
|
||||||
|
newFeedViewModel,
|
||||||
|
accountViewModel,
|
||||||
|
navInterceptor
|
||||||
|
)
|
||||||
|
Box(Modifier.padding(Size20dp), contentAlignment = Alignment.Center) {
|
||||||
|
ChannelFabColumn(accountViewModel, nav)
|
||||||
|
}
|
||||||
|
Divider(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxHeight() // fill the max height
|
||||||
|
.width(DividerThickness)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
second = {
|
||||||
|
selectedRoute?.let {
|
||||||
|
if (it.route == "Room") {
|
||||||
|
ChatroomScreen(
|
||||||
|
roomId = it.id,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it.route == "Channel") {
|
||||||
|
ChannelScreen(
|
||||||
|
channelId = it.id,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
strategy = strategy,
|
||||||
|
displayFeatures = accountViewModel.settings.displayFeatures.value,
|
||||||
|
foldAwareConfiguration = FoldAwareConfiguration.VerticalFoldsOnly,
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
fun ChatroomListScreenOnlyList(
|
||||||
|
knownFeedViewModel: NostrChatroomListKnownFeedViewModel,
|
||||||
|
newFeedViewModel: NostrChatroomListNewFeedViewModel,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
val pagerState = rememberPagerState() { 2 }
|
val pagerState = rememberPagerState() { 2 }
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
@@ -116,7 +248,6 @@ fun ChatroomListScreen(
|
|||||||
|
|
||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(end = 5.dp)
|
|
||||||
.size(40.dp)
|
.size(40.dp)
|
||||||
.align(Alignment.CenterEnd),
|
.align(Alignment.CenterEnd),
|
||||||
onClick = { moreActionsExpanded = true }
|
onClick = { moreActionsExpanded = true }
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
|
import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
|
import androidx.compose.foundation.lazy.grid.LazyGridState
|
||||||
|
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||||
|
import androidx.compose.foundation.lazy.grid.itemsIndexed
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.PagerState
|
import androidx.compose.foundation.pager.PagerState
|
||||||
@@ -238,7 +242,48 @@ private fun DiscoverFeedLoaded(
|
|||||||
) {
|
) {
|
||||||
itemsIndexed(state.feed.value, key = { _, item -> item.idHex }) { _, item ->
|
itemsIndexed(state.feed.value, key = { _, item -> item.idHex }) { _, item ->
|
||||||
val defaultModifier = remember {
|
val defaultModifier = remember {
|
||||||
Modifier.fillMaxWidth().animateItemPlacement()
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.animateItemPlacement()
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(defaultModifier) {
|
||||||
|
ChannelCardCompose(
|
||||||
|
baseNote = item,
|
||||||
|
routeForLastRead = routeForLastRead,
|
||||||
|
modifier = Modifier,
|
||||||
|
forceEventKind = forceEventKind,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
private fun DiscoverFeedTwoColumnsLoaded(
|
||||||
|
state: FeedState.Loaded,
|
||||||
|
routeForLastRead: String?,
|
||||||
|
listState: LazyGridState,
|
||||||
|
forceEventKind: Int?,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: (String) -> Unit
|
||||||
|
) {
|
||||||
|
LazyVerticalGrid(
|
||||||
|
columns = GridCells.Fixed(2),
|
||||||
|
contentPadding = PaddingValues(
|
||||||
|
top = 10.dp,
|
||||||
|
bottom = 10.dp
|
||||||
|
),
|
||||||
|
state = listState
|
||||||
|
) {
|
||||||
|
itemsIndexed(state.feed.value, key = { _, item -> item.idHex }) { _, item ->
|
||||||
|
val defaultModifier = remember {
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.animateItemPlacement()
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(defaultModifier) {
|
Row(defaultModifier) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import androidx.compose.material3.Scaffold
|
|||||||
import androidx.compose.material3.SheetValue
|
import androidx.compose.material3.SheetValue
|
||||||
import androidx.compose.material3.rememberDrawerState
|
import androidx.compose.material3.rememberDrawerState
|
||||||
import androidx.compose.material3.rememberModalBottomSheetState
|
import androidx.compose.material3.rememberModalBottomSheetState
|
||||||
|
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.DisposableEffect
|
import androidx.compose.runtime.DisposableEffect
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -474,7 +475,11 @@ private fun WritePermissionButtons(
|
|||||||
|
|
||||||
when (currentRoute) {
|
when (currentRoute) {
|
||||||
Route.Home.base -> NewNoteButton(accountViewModel, nav)
|
Route.Home.base -> NewNoteButton(accountViewModel, nav)
|
||||||
Route.Message.base -> ChannelFabColumn(accountViewModel, nav)
|
Route.Message.base -> {
|
||||||
|
if (accountViewModel.settings.windowSizeClass.value?.widthSizeClass == WindowWidthSizeClass.Compact) {
|
||||||
|
ChannelFabColumn(accountViewModel, nav)
|
||||||
|
}
|
||||||
|
}
|
||||||
Route.Video.base -> NewImageButton(accountViewModel, nav, navScrollToTop)
|
Route.Video.base -> NewImageButton(accountViewModel, nav, navScrollToTop)
|
||||||
Route.Community.base -> {
|
Route.Community.base -> {
|
||||||
val communityId by remember(navEntryState.value) {
|
val communityId by remember(navEntryState.value) {
|
||||||
|
|||||||
Reference in New Issue
Block a user