Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Refactor UI components #135

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions app/src/main/java/com/xinto/opencord/di/StoreModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ val storeModule = module {
singleOf(::SessionStoreImpl) bind SessionStore::class
singleOf(::UnreadStoreImpl) bind UnreadStore::class
singleOf(::ReactionStoreImpl) bind ReactionStore::class
singleOf(::PersistentDataStoreImpl) bind PersistentDataStore::class
}
16 changes: 12 additions & 4 deletions app/src/main/java/com/xinto/opencord/di/ViewModelModule.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package com.xinto.opencord.di

import com.xinto.opencord.ui.screens.home.panels.channel.HomeChannelsPanelViewModel
import com.xinto.opencord.ui.screens.home.panels.chat.HomeChatPanelViewModel
import com.xinto.opencord.ui.screens.home.panels.guild.GuildsViewModel
import com.xinto.opencord.ui.screens.home.panels.messagemenu.MessageMenuViewModel
import com.xinto.opencord.ui.screens.home.panels.user.HomeUserPanelViewModel
import com.xinto.opencord.ui.screens.login.LoginViewModel
import com.xinto.opencord.ui.screens.mentions.MentionsViewModel
import com.xinto.opencord.ui.screens.pins.PinsScreenViewModel
import com.xinto.opencord.ui.viewmodel.*
import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.dsl.module

val viewModelModule = module {
viewModelOf(::LoginViewModel)
viewModelOf(::ChatViewModel)
viewModelOf(::HomeChatPanelViewModel)
viewModelOf(::GuildsViewModel)
viewModelOf(::ChannelsViewModel)
viewModelOf(::ChannelPinsViewModel)
viewModelOf(::CurrentUserViewModel)
viewModelOf(::HomeChannelsPanelViewModel)
viewModelOf(::PinsScreenViewModel)
viewModelOf(::HomeUserPanelViewModel)
viewModelOf(::MessageMenuViewModel)
viewModelOf(::MentionsViewModel)
viewModelOf(::ChatInputViewModel)
Expand Down
95 changes: 95 additions & 0 deletions app/src/main/java/com/xinto/opencord/store/PersistentDataStore.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.xinto.opencord.store

import android.content.Context
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.stringSetPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

interface PersistentDataStore {

fun observeCurrentGuild(): Flow<Long>
fun observeCurrentChannel(): Flow<Long>
fun observeCollapsedCategories(): Flow<List<Long>>

suspend fun updateCurrentGuild(guildId: Long)
suspend fun updateCurrentChannel(channelId: Long)
suspend fun toggleCategory(categoryId: Long)
suspend fun collapseCategory(categoryId: Long)
suspend fun expandCategory(categoryId: Long)

}

class PersistentDataStoreImpl(
private val context: Context
) : PersistentDataStore {

private val Context.dataStore by preferencesDataStore("persistent")

override fun observeCurrentGuild(): Flow<Long> {
return context.dataStore.data.map { preferences ->
preferences[CURRENT_GUILD_KEY] ?: 0L
}
}

override fun observeCurrentChannel(): Flow<Long> {
return context.dataStore.data.map { preferences ->
preferences[CURRENT_CHANNEL_KEY] ?: 0L
}
}

override fun observeCollapsedCategories(): Flow<List<Long>> {
return context.dataStore.data.map { preferences ->
(preferences[COLLAPSED_CATEGORIES_KEY] ?: emptySet()).mapNotNull {
it.toLongOrNull()
}
}
}

override suspend fun updateCurrentGuild(guildId: Long) {
context.dataStore.edit { preferences ->
preferences[CURRENT_GUILD_KEY] = guildId
}
}

override suspend fun updateCurrentChannel(channelId: Long) {
context.dataStore.edit { preferences ->
preferences[CURRENT_CHANNEL_KEY] = channelId
}
}

override suspend fun toggleCategory(categoryId: Long) {
context.dataStore.edit { preferences ->
val current = preferences[COLLAPSED_CATEGORIES_KEY] ?: emptySet()
val stringCategoryId = categoryId.toString()
if (current.contains(stringCategoryId)) {
preferences[COLLAPSED_CATEGORIES_KEY] = current - stringCategoryId
} else {
preferences[COLLAPSED_CATEGORIES_KEY] = current + stringCategoryId
}
}
}

override suspend fun expandCategory(categoryId: Long) {
context.dataStore.edit { preferences ->
val current = preferences[COLLAPSED_CATEGORIES_KEY] ?: emptySet()
preferences[COLLAPSED_CATEGORIES_KEY] = current - categoryId.toString()
}
}

override suspend fun collapseCategory(categoryId: Long) {
context.dataStore.edit { preferences ->
val current = preferences[COLLAPSED_CATEGORIES_KEY] ?: emptySet()
preferences[COLLAPSED_CATEGORIES_KEY] = current + categoryId.toString()
}
}

private companion object {
val CURRENT_GUILD_KEY = longPreferencesKey("CURRENT_GULD")
val CURRENT_CHANNEL_KEY = longPreferencesKey("CURRENT_CHANNEL")
val COLLAPSED_CATEGORIES_KEY = stringSetPreferencesKey("COLLAPSED_CATEGORIES")
}

}
53 changes: 19 additions & 34 deletions app/src/main/java/com/xinto/opencord/ui/screens/home/HomeScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,17 @@ import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
Expand All @@ -17,20 +26,15 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import com.xinto.opencord.ui.navigation.PinsScreenData
import com.xinto.opencord.ui.screens.home.panels.HomeNavButtons
import com.xinto.opencord.ui.screens.home.panels.channel.ChannelsList
import com.xinto.opencord.ui.screens.home.panels.chat.Chat
import com.xinto.opencord.ui.screens.home.panels.currentuser.CurrentUser
import com.xinto.opencord.ui.screens.home.panels.guild.GuildsList
import com.xinto.opencord.ui.screens.home.panels.channel.HomeChannelsPanel
import com.xinto.opencord.ui.screens.home.panels.chat.HomeChatPanel
import com.xinto.opencord.ui.screens.home.panels.guild.HomeGuildsPanel
import com.xinto.opencord.ui.screens.home.panels.member.MembersList
import com.xinto.opencord.ui.screens.home.panels.user.HomeUserPanel
import com.xinto.opencord.ui.util.animateCornerBasedShapeAsState
import com.xinto.opencord.ui.viewmodel.ChannelsViewModel
import com.xinto.opencord.ui.viewmodel.ChatViewModel
import com.xinto.opencord.ui.viewmodel.CurrentUserViewModel
import com.xinto.opencord.ui.viewmodel.GuildsViewModel
import io.github.materiiapps.panels.SwipePanels
import io.github.materiiapps.panels.SwipePanelsValue
import io.github.materiiapps.panels.rememberSwipePanelsState
import org.koin.androidx.compose.getViewModel

@Composable
fun HomeScreen(
Expand All @@ -41,12 +45,6 @@ fun HomeScreen(
onFriendsClick: () -> Unit,
modifier: Modifier = Modifier,
) {
val currentUserViewModel: CurrentUserViewModel = getViewModel()
val chatViewModel: ChatViewModel = getViewModel()
val guildsViewModel: GuildsViewModel = getViewModel()
val channelsViewModel: ChannelsViewModel = getViewModel()

val channelsListState = rememberLazyListState()
val panelState = rememberSwipePanelsState()

BackHandler(enabled = panelState.currentValue != SwipePanelsValue.Center) {
Expand All @@ -71,28 +69,21 @@ fun HomeScreen(
Row(
modifier = Modifier.weight(1f),
) {
GuildsList(
HomeGuildsPanel(
modifier = Modifier
.fillMaxHeight()
.width(72.dp),
onGuildSelect = channelsViewModel::load,
viewModel = guildsViewModel,
)
ChannelsList(
HomeChannelsPanel(
modifier = Modifier
.fillMaxHeight()
.weight(1f),
onChannelSelect = chatViewModel::load,
viewModel = channelsViewModel,
lazyListState = channelsListState,
rushiiMachine marked this conversation as resolved.
Show resolved Hide resolved
)
}
CurrentUser(
HomeUserPanel(
modifier = Modifier
.fillMaxWidth()
.padding(start = 6.dp),
viewModel = currentUserViewModel,
onSettingsClick = onSettingsClick,
)
}

Expand All @@ -119,13 +110,7 @@ fun HomeScreen(
},
)

Chat(
onChannelsButtonClick = panelState::openStart,
onMembersButtonClick = panelState::openEnd,
onPinsButtonClick = {
onPinsClick(PinsScreenData(channelsViewModel.selectedChannelId))
},
viewModel = chatViewModel,
HomeChatPanel(
modifier = Modifier
.fillMaxSize()
.clip(centerPanelShape),
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.xinto.opencord.ui.screens.home.panels.channel

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.LocalAbsoluteTonalElevation
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.snapshots.SnapshotStateMap
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.xinto.opencord.ui.screens.home.panels.channel.model.CategoryItemData
import com.xinto.opencord.ui.screens.home.panels.channel.model.ChannelItemData
import org.koin.androidx.compose.koinViewModel

@Composable
fun HomeChannelsPanel(modifier: Modifier = Modifier) {
val viewModel: HomeChannelsPanelViewModel = koinViewModel()

HomeChannelsPanel(
state = viewModel.state,
onChannelSelect = viewModel::selectChannel,
onCategoryClick = viewModel::toggleCategory,
guildBannerUrl = viewModel.guildBannerUrl,
guildBoostLevel = viewModel.guildBoostLevel,
guildName = viewModel.guildName,
selectedChannelId = viewModel.selectedChannelId,
categoryChannels = viewModel.categoryChannels,
noCategoryChannels = viewModel.noCategoryChannels,
modifier = modifier,
)
}

@Composable
fun HomeChannelsPanel(
state: HomeChannelsPanelState,
onChannelSelect: (Long) -> Unit,
onCategoryClick: (Long) -> Unit,
guildBannerUrl: String?,
guildBoostLevel: Int,
guildName: String,
selectedChannelId: Long,
categoryChannels: SnapshotStateMap<Long, CategoryItemData>,
noCategoryChannels: SnapshotStateMap<Long, ChannelItemData>,
modifier: Modifier = Modifier,
lazyListState: LazyListState = rememberLazyListState(),
) {
CompositionLocalProvider(LocalAbsoluteTonalElevation provides 1.dp) {
Surface(
modifier = modifier,
shape = MaterialTheme.shapes.large,
) {
when (state) {
is HomeChannelsPanelState.Unselected -> {
ChannelsListUnselected(
modifier = Modifier.fillMaxSize(),
)
}
is HomeChannelsPanelState.Loading -> {
ChannelsListLoading(
modifier = Modifier.fillMaxSize(),
)
}
is HomeChannelsPanelState.Loaded -> {
ChannelsListLoaded(
modifier = Modifier.fillMaxSize(),
onChannelSelect = onChannelSelect,
onCategoryClick = onCategoryClick,
bannerUrl = guildBannerUrl,
boostLevel = guildBoostLevel,
guildName = guildName,
selectedChannelId = selectedChannelId,
categoryChannels = categoryChannels,
noCategoryChannels = noCategoryChannels,
lazyListState = lazyListState,
)
}
is HomeChannelsPanelState.Error -> {

}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.xinto.opencord.ui.screens.home.panels.channel

sealed interface HomeChannelsPanelState {
object Unselected : HomeChannelsPanelState
object Loading : HomeChannelsPanelState
object Loaded : HomeChannelsPanelState
object Error : HomeChannelsPanelState
}