feat: support for categories
Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
parent
5251d3f7aa
commit
a2801b29d7
|
|
@ -2,8 +2,14 @@ package chat.revolt.api.internals
|
||||||
|
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.revolt.api.RevoltAPI
|
||||||
import chat.revolt.api.schemas.Channel
|
import chat.revolt.api.schemas.Channel
|
||||||
|
import chat.revolt.api.schemas.Server
|
||||||
import chat.revolt.api.schemas.User
|
import chat.revolt.api.schemas.User
|
||||||
|
|
||||||
|
sealed class CategorisedChannelList {
|
||||||
|
data class Channel(val channel: chat.revolt.api.schemas.Channel) : CategorisedChannelList()
|
||||||
|
data class Category(val category: chat.revolt.api.schemas.Category) : CategorisedChannelList()
|
||||||
|
}
|
||||||
|
|
||||||
object ChannelUtils {
|
object ChannelUtils {
|
||||||
fun resolveDMName(channel: Channel): String? {
|
fun resolveDMName(channel: Channel): String? {
|
||||||
return channel.name
|
return channel.name
|
||||||
|
|
@ -17,4 +23,31 @@ object ChannelUtils {
|
||||||
fun resolveDMPartner(channel: Channel): String? {
|
fun resolveDMPartner(channel: Channel): String? {
|
||||||
return channel.recipients?.first { u -> u != RevoltAPI.selfId }
|
return channel.recipients?.first { u -> u != RevoltAPI.selfId }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun categoriseServerFlat(server: Server): List<CategorisedChannelList> {
|
||||||
|
val output = mutableListOf<CategorisedChannelList>()
|
||||||
|
|
||||||
|
val uncategorised =
|
||||||
|
server.channels?.filter { c -> server.categories?.none { cat -> cat.channels?.contains(c) == true } == true }
|
||||||
|
?.mapNotNull {
|
||||||
|
RevoltAPI.channelCache[it]?.let { it1 ->
|
||||||
|
CategorisedChannelList.Channel(it1)
|
||||||
|
}
|
||||||
|
} ?: emptyList()
|
||||||
|
output.addAll(uncategorised)
|
||||||
|
|
||||||
|
val categories =
|
||||||
|
server.categories?.map { CategorisedChannelList.Category(it) } ?: emptyList()
|
||||||
|
categories.forEach {
|
||||||
|
output.add(it)
|
||||||
|
val channels = it.category.channels?.mapNotNull { c ->
|
||||||
|
RevoltAPI.channelCache[c]?.let { it1 ->
|
||||||
|
CategorisedChannelList.Channel(it1)
|
||||||
|
}
|
||||||
|
} ?: emptyList()
|
||||||
|
output.addAll(channels)
|
||||||
|
}
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -60,6 +60,7 @@ import chat.revolt.activities.RevoltTweenDp
|
||||||
import chat.revolt.activities.RevoltTweenFloat
|
import chat.revolt.activities.RevoltTweenFloat
|
||||||
import chat.revolt.api.REVOLT_FILES
|
import chat.revolt.api.REVOLT_FILES
|
||||||
import chat.revolt.api.RevoltAPI
|
import chat.revolt.api.RevoltAPI
|
||||||
|
import chat.revolt.api.internals.CategorisedChannelList
|
||||||
import chat.revolt.api.internals.ChannelUtils
|
import chat.revolt.api.internals.ChannelUtils
|
||||||
import chat.revolt.api.schemas.ChannelType
|
import chat.revolt.api.schemas.ChannelType
|
||||||
import chat.revolt.api.schemas.ServerFlags
|
import chat.revolt.api.schemas.ServerFlags
|
||||||
|
|
@ -138,6 +139,13 @@ fun RowScope.ChannelList(
|
||||||
.sortedBy { it.lastMessageID ?: it.id }
|
.sortedBy { it.lastMessageID ?: it.id }
|
||||||
.reversed()
|
.reversed()
|
||||||
|
|
||||||
|
val server = remember(serverId, RevoltAPI.serverCache) { RevoltAPI.serverCache[serverId] }
|
||||||
|
val categorisedChannels = remember(server, RevoltAPI.channelCache) {
|
||||||
|
server?.let {
|
||||||
|
ChannelUtils.categoriseServerFlat(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Surface(
|
Surface(
|
||||||
tonalElevation = 1.dp,
|
tonalElevation = 1.dp,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -262,8 +270,6 @@ fun RowScope.ChannelList(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val server = RevoltAPI.serverCache[serverId]
|
|
||||||
|
|
||||||
stickyHeader {
|
stickyHeader {
|
||||||
Box(
|
Box(
|
||||||
contentAlignment = Alignment.BottomStart,
|
contentAlignment = Alignment.BottomStart,
|
||||||
|
|
@ -435,7 +441,7 @@ fun RowScope.ChannelList(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server?.channels?.isEmpty() == true) {
|
if (categorisedChannels.isNullOrEmpty()) {
|
||||||
item {
|
item {
|
||||||
Column(
|
Column(
|
||||||
Modifier.weight(1f),
|
Modifier.weight(1f),
|
||||||
|
|
@ -458,30 +464,74 @@ fun RowScope.ChannelList(
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
items(
|
items(
|
||||||
server?.channels?.size ?: 0,
|
categorisedChannels.size ?: 0,
|
||||||
key = { server?.channels?.get(it) ?: "" }
|
key = { index ->
|
||||||
|
val channel = categorisedChannels.getOrNull(index)
|
||||||
|
channel?.let {
|
||||||
|
when (it) {
|
||||||
|
is CategorisedChannelList.Channel -> it.channel.id
|
||||||
|
is CategorisedChannelList.Category -> it.category.id
|
||||||
|
}
|
||||||
|
} ?: index
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
server?.channels?.get(it)?.let { channelId ->
|
when (val item = categorisedChannels.getOrNull(it)) {
|
||||||
RevoltAPI.channelCache[channelId]?.let { ch ->
|
is CategorisedChannelList.Channel -> {
|
||||||
|
val channel = item.channel
|
||||||
|
|
||||||
|
val partner =
|
||||||
|
if (channel.channelType == ChannelType.DirectMessage) RevoltAPI.userCache[ChannelUtils.resolveDMPartner(
|
||||||
|
channel
|
||||||
|
)] else null
|
||||||
|
|
||||||
DrawerChannel(
|
DrawerChannel(
|
||||||
name = ch.name ?: stringResource(R.string.unknown),
|
name = partner?.let { p -> User.resolveDefaultName(p) }
|
||||||
channelType = ch.channelType ?: ChannelType.TextChannel,
|
?: channel.name
|
||||||
selected = currentDestination == "channel/{channelId}" && currentChannel == ch.id,
|
?: stringResource(R.string.unknown),
|
||||||
hasUnread = ch.lastMessageID?.let { lastMessageID ->
|
channelType = channel.channelType ?: ChannelType.TextChannel,
|
||||||
|
selected = currentDestination == "channel/{channelId}" && currentChannel == channel.id,
|
||||||
|
hasUnread = channel.lastMessageID?.let { lastMessageID ->
|
||||||
RevoltAPI.unreads.hasUnread(
|
RevoltAPI.unreads.hasUnread(
|
||||||
ch.id!!,
|
channel.id!!,
|
||||||
lastMessageID
|
lastMessageID
|
||||||
)
|
)
|
||||||
} ?: false,
|
} ?: false,
|
||||||
|
dmPartnerIcon = partner?.avatar ?: channel.icon,
|
||||||
|
dmPartnerId = partner?.id,
|
||||||
|
dmPartnerName = partner?.let { p -> User.resolveDefaultName(p) },
|
||||||
|
dmPartnerStatus = presenceFromStatus(
|
||||||
|
status = partner?.status?.presence,
|
||||||
|
online = partner?.online ?: false
|
||||||
|
),
|
||||||
onClick = {
|
onClick = {
|
||||||
onChannelClick(ch.id ?: return@DrawerChannel)
|
onChannelClick(channel.id ?: return@DrawerChannel)
|
||||||
},
|
},
|
||||||
onLongClick = {
|
onLongClick = {
|
||||||
channelContextSheetTarget = ch.id ?: return@DrawerChannel
|
channelContextSheetTarget =
|
||||||
|
channel.id ?: return@DrawerChannel
|
||||||
channelContextSheetShown = true
|
channelContextSheetShown = true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is CategorisedChannelList.Category -> {
|
||||||
|
val category = item.category
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = category.title ?: stringResource(R.string.unknown),
|
||||||
|
style = MaterialTheme.typography.labelLarge,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(
|
||||||
|
start = 16.dp,
|
||||||
|
end = 16.dp,
|
||||||
|
top = 24.dp,
|
||||||
|
bottom = 16.dp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue