mirror of
https://github.com/LiveFastEatTrashRaccoon/RaccoonForLemmy.git
synced 2025-02-09 11:38:40 +01:00
fix: instance detail (#125)
* fix: improve sort and loading in instance detail * enhancement: move options menu to top bar in user and community detail
This commit is contained in:
parent
b73f84d89c
commit
157ffcf563
@ -26,6 +26,7 @@ import androidx.compose.material.icons.filled.ArrowCircleUp
|
||||
import androidx.compose.material.icons.filled.ClearAll
|
||||
import androidx.compose.material.icons.filled.Create
|
||||
import androidx.compose.material.icons.filled.ExpandLess
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material.icons.filled.Sync
|
||||
import androidx.compose.material.icons.filled.SyncDisabled
|
||||
import androidx.compose.material.icons.outlined.AddCircleOutline
|
||||
@ -57,10 +58,14 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.layout.positionInParent
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||
import cafe.adriel.voyager.core.screen.Screen
|
||||
@ -70,6 +75,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communityInfo.CommunityInfoScreen
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommunityHeader
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CustomDropDown
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.FloatingActionButtonMenu
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.FloatingActionButtonMenuItem
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.Option
|
||||
@ -97,6 +103,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.persistence.di.getSettingsR
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.onClick
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.rememberCallback
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.rememberCallbackArgs
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||
@ -263,6 +270,93 @@ class CommunityDetailScreen(
|
||||
contentDescription = null,
|
||||
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
||||
)
|
||||
|
||||
// options menu
|
||||
Box {
|
||||
val options = listOf(
|
||||
Option(
|
||||
OptionId.Info,
|
||||
stringResource(MR.strings.community_detail_info)
|
||||
),
|
||||
Option(
|
||||
OptionId.InfoInstance,
|
||||
stringResource(MR.strings.community_detail_instance_info)
|
||||
),
|
||||
Option(
|
||||
OptionId.Block,
|
||||
stringResource(MR.strings.community_detail_block)
|
||||
),
|
||||
Option(
|
||||
OptionId.BlockInstance,
|
||||
stringResource(MR.strings.community_detail_block_instance)
|
||||
),
|
||||
)
|
||||
var optionsExpanded by remember { mutableStateOf(false) }
|
||||
var optionsOffset by remember { mutableStateOf(Offset.Zero) }
|
||||
Image(
|
||||
modifier = Modifier.onGloballyPositioned {
|
||||
optionsOffset = it.positionInParent()
|
||||
}.padding(start = Spacing.s).onClick(
|
||||
rememberCallback {
|
||||
optionsExpanded = true
|
||||
},
|
||||
),
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
contentDescription = null,
|
||||
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
||||
)
|
||||
CustomDropDown(
|
||||
expanded = optionsExpanded,
|
||||
onDismiss = {
|
||||
optionsExpanded = false
|
||||
},
|
||||
offset = DpOffset(
|
||||
x = optionsOffset.x.toLocalDp(),
|
||||
y = optionsOffset.y.toLocalDp(),
|
||||
),
|
||||
) {
|
||||
options.forEach { option ->
|
||||
Text(
|
||||
modifier = Modifier.padding(
|
||||
horizontal = Spacing.m,
|
||||
vertical = Spacing.s,
|
||||
).onClick(
|
||||
rememberCallback {
|
||||
optionsExpanded = false
|
||||
when (option.id) {
|
||||
OptionId.BlockInstance -> model.reduce(
|
||||
CommunityDetailMviModel.Intent.BlockInstance
|
||||
)
|
||||
|
||||
OptionId.Block -> model.reduce(
|
||||
CommunityDetailMviModel.Intent.Block
|
||||
)
|
||||
|
||||
OptionId.InfoInstance -> {
|
||||
navigationCoordinator.getRootNavigator()
|
||||
?.push(
|
||||
InstanceInfoScreen(
|
||||
url = uiState.community.instanceUrl,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
OptionId.Info -> {
|
||||
navigationCoordinator.getBottomNavigator()
|
||||
?.show(
|
||||
CommunityInfoScreen(uiState.community),
|
||||
)
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
},
|
||||
),
|
||||
text = option.text,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
navigationIcon = {
|
||||
val navigator = navigationCoordinator.getRootNavigator()
|
||||
@ -381,53 +475,10 @@ class CommunityDetailScreen(
|
||||
CommunityHeader(
|
||||
community = uiState.community,
|
||||
autoLoadImages = uiState.autoLoadImages,
|
||||
options = listOf(
|
||||
Option(
|
||||
OptionId.Info,
|
||||
stringResource(MR.strings.community_detail_info)
|
||||
),
|
||||
Option(
|
||||
OptionId.InfoInstance,
|
||||
stringResource(MR.strings.community_detail_instance_info)
|
||||
),
|
||||
Option(
|
||||
OptionId.Block,
|
||||
stringResource(MR.strings.community_detail_block)
|
||||
),
|
||||
Option(
|
||||
OptionId.BlockInstance,
|
||||
stringResource(MR.strings.community_detail_block_instance)
|
||||
),
|
||||
),
|
||||
onOpenImage = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.getRootNavigator()
|
||||
?.push(ZoomableImageScreen(url))
|
||||
},
|
||||
onOptionSelected = rememberCallbackArgs { optionId ->
|
||||
when (optionId) {
|
||||
OptionId.BlockInstance -> model.reduce(
|
||||
CommunityDetailMviModel.Intent.BlockInstance
|
||||
)
|
||||
|
||||
OptionId.Block -> model.reduce(CommunityDetailMviModel.Intent.Block)
|
||||
|
||||
OptionId.InfoInstance -> {
|
||||
navigationCoordinator.getRootNavigator()?.push(
|
||||
InstanceInfoScreen(
|
||||
url = uiState.community.instanceUrl,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
OptionId.Info -> {
|
||||
navigationCoordinator.getBottomNavigator()?.show(
|
||||
CommunityInfoScreen(uiState.community),
|
||||
)
|
||||
}
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
},
|
||||
)
|
||||
Spacer(modifier = Modifier.height(Spacing.m))
|
||||
}
|
||||
|
@ -14,34 +14,24 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.CalendarViewMonth
|
||||
import androidx.compose.material.icons.filled.Group
|
||||
import androidx.compose.material.icons.outlined.Info
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.FilterQuality
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.layout.positionInParent
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.IconSize
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.getPrettyNumber
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.onClick
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.rememberCallback
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
@ -51,8 +41,6 @@ fun CommunityHeader(
|
||||
community: CommunityModel,
|
||||
modifier: Modifier = Modifier,
|
||||
autoLoadImages: Boolean = true,
|
||||
options: List<Option> = emptyList(),
|
||||
onOptionSelected: ((OptionId) -> Unit)? = null,
|
||||
onOpenImage: ((String) -> Unit)? = null,
|
||||
) {
|
||||
Box(
|
||||
@ -86,53 +74,6 @@ fun CommunityHeader(
|
||||
}
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier.padding(top = Spacing.xs, end = Spacing.s).align(Alignment.TopEnd)
|
||||
) {
|
||||
if (options.isNotEmpty()) {
|
||||
var optionsExpanded by remember { mutableStateOf(false) }
|
||||
var optionsOffset by remember { mutableStateOf(Offset.Zero) }
|
||||
Icon(
|
||||
modifier = Modifier.onGloballyPositioned {
|
||||
optionsOffset = it.positionInParent()
|
||||
}.onClick(
|
||||
rememberCallback {
|
||||
optionsExpanded = true
|
||||
},
|
||||
),
|
||||
imageVector = Icons.Outlined.Info,
|
||||
contentDescription = null,
|
||||
)
|
||||
CustomDropDown(
|
||||
expanded = optionsExpanded,
|
||||
onDismiss = {
|
||||
optionsExpanded = false
|
||||
},
|
||||
offset = DpOffset(
|
||||
x = optionsOffset.x.toLocalDp(),
|
||||
y = optionsOffset.y.toLocalDp(),
|
||||
// y = (-50).dp,
|
||||
),
|
||||
) {
|
||||
options.forEach { option ->
|
||||
Text(
|
||||
modifier = Modifier.padding(
|
||||
horizontal = Spacing.m,
|
||||
vertical = Spacing.s,
|
||||
).onClick(
|
||||
rememberCallback {
|
||||
optionsExpanded = false
|
||||
onOptionSelected?.invoke(option.id)
|
||||
},
|
||||
),
|
||||
text = option.text,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().padding(Spacing.s).align(Alignment.Center),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
|
@ -17,27 +17,18 @@ import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Cake
|
||||
import androidx.compose.material.icons.filled.Padding
|
||||
import androidx.compose.material.icons.filled.Reply
|
||||
import androidx.compose.material.icons.outlined.MoreVert
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.FilterQuality
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.layout.positionInParent
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.IconSize
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||
@ -45,7 +36,6 @@ import com.github.diegoberaldin.raccoonforlemmy.core.utils.getPrettyNumber
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.onClick
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.prettifyDate
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.rememberCallback
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
@ -55,8 +45,6 @@ fun UserHeader(
|
||||
user: UserModel,
|
||||
modifier: Modifier = Modifier,
|
||||
autoLoadImages: Boolean = true,
|
||||
options: List<Option> = emptyList(),
|
||||
onOptionSelected: ((OptionId) -> Unit)? = null,
|
||||
onOpenImage: ((String) -> Unit)? = null,
|
||||
) {
|
||||
Box(
|
||||
@ -89,52 +77,6 @@ fun UserHeader(
|
||||
}
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier.padding(top = Spacing.xs, end = Spacing.s).align(Alignment.TopEnd)
|
||||
) {
|
||||
// options menu
|
||||
if (options.isNotEmpty()) {
|
||||
var optionsExpanded by remember { mutableStateOf(false) }
|
||||
var optionsOffset by remember { mutableStateOf(Offset.Zero) }
|
||||
Icon(
|
||||
modifier = Modifier.onGloballyPositioned {
|
||||
optionsOffset = it.positionInParent()
|
||||
}.onClick(
|
||||
rememberCallback {
|
||||
optionsExpanded = true
|
||||
},
|
||||
),
|
||||
imageVector = Icons.Outlined.MoreVert,
|
||||
contentDescription = null,
|
||||
)
|
||||
CustomDropDown(
|
||||
expanded = optionsExpanded,
|
||||
onDismiss = {
|
||||
optionsExpanded = false
|
||||
},
|
||||
offset = DpOffset(
|
||||
x = optionsOffset.x.toLocalDp(),
|
||||
y = optionsOffset.y.toLocalDp(),
|
||||
),
|
||||
) {
|
||||
options.forEach { option ->
|
||||
Text(
|
||||
modifier = Modifier.padding(
|
||||
horizontal = Spacing.m,
|
||||
vertical = Spacing.s,
|
||||
).onClick(
|
||||
rememberCallback {
|
||||
optionsExpanded = false
|
||||
onOptionSelected?.invoke(option.id)
|
||||
},
|
||||
),
|
||||
text = option.text,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().padding(Spacing.s).align(Alignment.Center),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
|
@ -10,7 +10,6 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
@ -21,7 +20,6 @@ import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||
import androidx.compose.material.pullrefresh.pullRefresh
|
||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
@ -38,7 +36,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.unit.dp
|
||||
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||
import cafe.adriel.voyager.core.screen.Screen
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||
@ -73,11 +70,11 @@ class InstanceInfoScreen(
|
||||
)
|
||||
@Composable
|
||||
override fun Content() {
|
||||
val model = rememberScreenModel { getInstanceInfoViewModel(url) }
|
||||
val instanceName = url.replace("https://", "")
|
||||
val model = rememberScreenModel(instanceName) { getInstanceInfoViewModel(url) }
|
||||
model.bindToLifecycle(key)
|
||||
val uiState by model.uiState.collectAsState()
|
||||
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||
val instanceName = url.replace("https://", "")
|
||||
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
|
||||
val settingsRepository = remember { getSettingsRepository() }
|
||||
val settings by settingsRepository.currentSettings.collectAsState()
|
||||
@ -156,6 +153,7 @@ class InstanceInfoScreen(
|
||||
SortType.New,
|
||||
SortType.NewComments,
|
||||
SortType.MostComments,
|
||||
SortType.Old,
|
||||
SortType.Top.Generic,
|
||||
),
|
||||
expandTop = true,
|
||||
@ -226,7 +224,7 @@ class InstanceInfoScreen(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (uiState.loading && uiState.communities.isEmpty()) {
|
||||
if (uiState.communities.isEmpty()) {
|
||||
items(5) {
|
||||
CommunityItemPlaceholder()
|
||||
}
|
||||
@ -252,17 +250,6 @@ class InstanceInfoScreen(
|
||||
if (!uiState.loading && !uiState.refreshing && uiState.canFetchMore) {
|
||||
model.reduce(InstanceInfoMviModel.Intent.LoadNextPage)
|
||||
}
|
||||
if (uiState.loading && !uiState.refreshing) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxWidth().padding(Spacing.xs),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.size(25.dp),
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,22 +82,30 @@ class InstanceInfoViewModel(
|
||||
auth = auth,
|
||||
instance = instance,
|
||||
page = currentPage,
|
||||
limit = 50,
|
||||
listingType = ListingType.Local,
|
||||
sortType = currentState.sortType,
|
||||
resultType = SearchResultType.Communities,
|
||||
limit = 50,
|
||||
)?.filterIsInstance<CommunityModel>()
|
||||
?.let {
|
||||
if (refreshing) {
|
||||
it
|
||||
} else {
|
||||
// prevents accidental duplication
|
||||
it.filter { c1 -> currentState.communities.none { c2 -> c1.id == c2.id } }
|
||||
}
|
||||
}
|
||||
if (!itemList.isNullOrEmpty()) {
|
||||
currentPage++
|
||||
}
|
||||
val itemsToAdd = itemList.orEmpty().filter { e -> e.instanceUrl == url }
|
||||
mvi.updateState {
|
||||
val newItems = if (refreshing) {
|
||||
itemList?.filter { e -> e.instanceUrl == url }.orEmpty()
|
||||
} else {
|
||||
it.communities + itemList?.filter { e -> e.instanceUrl == url }.orEmpty()
|
||||
}
|
||||
it.copy(
|
||||
communities = newItems,
|
||||
communities = if (refreshing) {
|
||||
itemsToAdd
|
||||
} else {
|
||||
it.communities + itemsToAdd
|
||||
},
|
||||
loading = false,
|
||||
canFetchMore = itemList?.isEmpty() != true,
|
||||
refreshing = false,
|
||||
|
@ -122,7 +122,8 @@ class SavedItemsViewModel(
|
||||
currentPage = 1
|
||||
mvi.updateState {
|
||||
it.copy(
|
||||
canFetchMore = true, refreshing = true
|
||||
canFetchMore = true,
|
||||
refreshing = true,
|
||||
)
|
||||
}
|
||||
loadNextPage()
|
||||
|
@ -24,6 +24,7 @@ import androidx.compose.material.icons.filled.ArrowCircleDown
|
||||
import androidx.compose.material.icons.filled.ArrowCircleUp
|
||||
import androidx.compose.material.icons.filled.Chat
|
||||
import androidx.compose.material.icons.filled.ExpandLess
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material.pullrefresh.PullRefreshIndicator
|
||||
import androidx.compose.material.pullrefresh.pullRefresh
|
||||
import androidx.compose.material.pullrefresh.rememberPullRefreshState
|
||||
@ -51,11 +52,15 @@ import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.layout.positionInParent
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.DpOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||
import cafe.adriel.voyager.core.screen.Screen
|
||||
@ -67,6 +72,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.chat.InboxChatScre
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommentCard
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommentCardPlaceholder
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CustomDropDown
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.FloatingActionButtonMenu
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.FloatingActionButtonMenuItem
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.Option
|
||||
@ -94,6 +100,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.persistence.di.getSettingsR
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.onClick
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.rememberCallback
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.rememberCallbackArgs
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.SortType
|
||||
@ -217,6 +224,7 @@ class UserDetailScreen(
|
||||
)
|
||||
},
|
||||
actions = {
|
||||
// sort button
|
||||
Image(
|
||||
modifier = Modifier.onClick(
|
||||
rememberCallback {
|
||||
@ -230,6 +238,69 @@ class UserDetailScreen(
|
||||
contentDescription = null,
|
||||
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
||||
)
|
||||
|
||||
// options menu
|
||||
Box {
|
||||
val options = listOf(
|
||||
Option(
|
||||
OptionId.Block,
|
||||
stringResource(MR.strings.community_detail_block)
|
||||
),
|
||||
Option(
|
||||
OptionId.BlockInstance,
|
||||
stringResource(MR.strings.community_detail_block_instance)
|
||||
),
|
||||
)
|
||||
var optionsExpanded by remember { mutableStateOf(false) }
|
||||
var optionsOffset by remember { mutableStateOf(Offset.Zero) }
|
||||
Image(
|
||||
modifier = Modifier.onGloballyPositioned {
|
||||
optionsOffset = it.positionInParent()
|
||||
}.padding(start = Spacing.s).onClick(
|
||||
rememberCallback {
|
||||
optionsExpanded = true
|
||||
},
|
||||
),
|
||||
imageVector = Icons.Default.MoreVert,
|
||||
contentDescription = null,
|
||||
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
||||
)
|
||||
CustomDropDown(
|
||||
expanded = optionsExpanded,
|
||||
onDismiss = {
|
||||
optionsExpanded = false
|
||||
},
|
||||
offset = DpOffset(
|
||||
x = optionsOffset.x.toLocalDp(),
|
||||
y = optionsOffset.y.toLocalDp(),
|
||||
),
|
||||
) {
|
||||
options.forEach { option ->
|
||||
Text(
|
||||
modifier = Modifier.padding(
|
||||
horizontal = Spacing.m,
|
||||
vertical = Spacing.s,
|
||||
).onClick(
|
||||
rememberCallback {
|
||||
optionsExpanded = false
|
||||
when (option.id) {
|
||||
OptionId.BlockInstance -> model.reduce(
|
||||
UserDetailMviModel.Intent.BlockInstance
|
||||
)
|
||||
|
||||
OptionId.Block -> model.reduce(
|
||||
UserDetailMviModel.Intent.Block
|
||||
)
|
||||
|
||||
else -> Unit
|
||||
}
|
||||
},
|
||||
),
|
||||
text = option.text,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
navigationIcon = {
|
||||
val navigator = navigationCoordinator.getRootNavigator()
|
||||
@ -319,27 +390,10 @@ class UserDetailScreen(
|
||||
UserHeader(
|
||||
user = uiState.user,
|
||||
autoLoadImages = uiState.autoLoadImages,
|
||||
options = listOf(
|
||||
Option(
|
||||
OptionId.Block,
|
||||
stringResource(MR.strings.community_detail_block)
|
||||
),
|
||||
Option(
|
||||
OptionId.BlockInstance,
|
||||
stringResource(MR.strings.community_detail_block_instance)
|
||||
),
|
||||
),
|
||||
onOpenImage = rememberCallbackArgs { url ->
|
||||
navigationCoordinator.getRootNavigator()
|
||||
?.push(ZoomableImageScreen(url))
|
||||
},
|
||||
onOptionSelected = rememberCallbackArgs { optionId ->
|
||||
when (optionId) {
|
||||
OptionId.BlockInstance -> model.reduce(UserDetailMviModel.Intent.BlockInstance)
|
||||
OptionId.Block -> model.reduce(UserDetailMviModel.Intent.Block)
|
||||
else -> Unit
|
||||
}
|
||||
},
|
||||
)
|
||||
SectionSelector(
|
||||
titles = listOf(
|
||||
|
@ -16,6 +16,7 @@ interface ManageSubscriptionsMviModel :
|
||||
}
|
||||
|
||||
data class UiState(
|
||||
val initial: Boolean = true,
|
||||
val refreshing: Boolean = false,
|
||||
val multiCommunities: List<MultiCommunityModel> = emptyList(),
|
||||
val communities: List<CommunityModel> = emptyList(),
|
||||
|
@ -61,6 +61,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.Swipeab
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getDrawerCoordinator
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getFabNestedScrollConnection
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getNavigationCoordinator
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.selectcommunity.CommunityItemPlaceholder
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.onClick
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.rememberCallback
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.rememberCallbackArgs
|
||||
@ -256,6 +257,11 @@ class ManageSubscriptionsScreen : Screen {
|
||||
)
|
||||
}
|
||||
}
|
||||
if (uiState.initial) {
|
||||
items(5) {
|
||||
CommunityItemPlaceholder()
|
||||
}
|
||||
}
|
||||
items(uiState.communities) { community ->
|
||||
val endColor = MaterialTheme.colorScheme.secondary
|
||||
SwipeableCard(
|
||||
@ -301,9 +307,9 @@ class ManageSubscriptionsScreen : Screen {
|
||||
)
|
||||
}
|
||||
|
||||
if (uiState.multiCommunities.isEmpty() && uiState.communities.isEmpty()) {
|
||||
if (uiState.multiCommunities.isEmpty() && uiState.communities.isEmpty() && !uiState.initial) {
|
||||
item {
|
||||
androidx.compose.material.Text(
|
||||
Text(
|
||||
modifier = Modifier.fillMaxWidth().padding(top = Spacing.xs),
|
||||
textAlign = TextAlign.Center,
|
||||
text = stringResource(MR.strings.message_empty_list),
|
||||
@ -314,13 +320,15 @@ class ManageSubscriptionsScreen : Screen {
|
||||
}
|
||||
}
|
||||
|
||||
PullRefreshIndicator(
|
||||
refreshing = uiState.refreshing,
|
||||
state = pullRefreshState,
|
||||
modifier = Modifier.align(Alignment.TopCenter),
|
||||
backgroundColor = MaterialTheme.colorScheme.background,
|
||||
contentColor = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
if (!uiState.initial) {
|
||||
PullRefreshIndicator(
|
||||
refreshing = uiState.refreshing,
|
||||
state = pullRefreshState,
|
||||
modifier = Modifier.align(Alignment.TopCenter),
|
||||
backgroundColor = MaterialTheme.colorScheme.background,
|
||||
contentColor = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -88,6 +88,7 @@ class ManageSubscriptionsViewModel(
|
||||
mvi.updateState {
|
||||
it.copy(
|
||||
refreshing = false,
|
||||
initial = false,
|
||||
communities = communities,
|
||||
multiCommunities = multiCommunitites,
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user