Skip to content

Commit

Permalink
Implement migrated chat list screen
Browse files Browse the repository at this point in the history
  • Loading branch information
Taewan-P committed Feb 27, 2025
1 parent 7017fc3 commit 9a3661b
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ fun NavGraphBuilder.homeScreenNavigation(navController: NavHostController) {
)
},
navigateToNewChat = {
val enabledPlatformString = it.joinToString(",") { v -> v.name }
val enabledPlatformString = it.joinToString(",")
navController.navigate(
Route.CHAT_ROOM
.replace(oldValue = "{chatRoomId}", newValue = "0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,15 @@ import androidx.compose.ui.draw.alpha
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import dev.chungjungsoo.gptmobile.R
import dev.chungjungsoo.gptmobile.data.dto.Platform

@Composable
fun PlatformCheckBoxItem(
modifier: Modifier = Modifier,
platform: Platform,
selected: Boolean,
enabled: Boolean = true,
title: String = stringResource(R.string.sample_item_title),
description: String? = stringResource(R.string.sample_item_description),
onClickEvent: (Platform) -> Unit
onClickEvent: () -> Unit
) {
val interactionSource = remember { MutableInteractionSource() }
val rowModifier = if (enabled) {
Expand All @@ -36,7 +35,7 @@ fun PlatformCheckBoxItem(
.clickable(
interactionSource = interactionSource,
indication = LocalIndication.current
) { onClickEvent.invoke(platform) }
) { onClickEvent.invoke() }
.padding(top = 12.dp, bottom = 12.dp, start = 16.dp, end = 16.dp)
} else {
modifier
Expand All @@ -51,9 +50,9 @@ fun PlatformCheckBoxItem(
) {
Checkbox(
enabled = enabled,
checked = platform.selected,
checked = selected,
interactionSource = interactionSource,
onCheckedChange = { onClickEvent.invoke(platform) }
onCheckedChange = { onClickEvent.invoke() }
)
Column(horizontalAlignment = Alignment.Start) {
Text(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,18 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import dev.chungjungsoo.gptmobile.R
import dev.chungjungsoo.gptmobile.data.database.entity.ChatRoomV2
import dev.chungjungsoo.gptmobile.data.dto.Platform
import dev.chungjungsoo.gptmobile.data.model.ApiType
import dev.chungjungsoo.gptmobile.data.database.entity.PlatformV2
import dev.chungjungsoo.gptmobile.presentation.common.PlatformCheckBoxItem
import dev.chungjungsoo.gptmobile.util.getPlatformTitleResources
import dev.chungjungsoo.gptmobile.util.getPlatformName

@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@Composable
fun HomeScreen(
homeViewModel: HomeViewModel = hiltViewModel(),
settingOnClick: () -> Unit,
onExistingChatClick: (ChatRoomV2) -> Unit,
navigateToNewChat: (enabledPlatforms: List<ApiType>) -> Unit
navigateToNewChat: (enabledPlatforms: List<String>) -> Unit
) {
val platformTitles = getPlatformTitleResources()
val listState = rememberLazyListState()
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val chatListState by homeViewModel.chatListState.collectAsStateWithLifecycle()
Expand Down Expand Up @@ -107,7 +105,7 @@ fun HomeScreen(
topBar = {
HomeTopAppBar(
chatListState.isSelectionMode,
selectedChats = chatListState.selected.count { it },
selectedChats = chatListState.selectedChats.count { it },
scrollBehavior,
actionOnClick = {
if (chatListState.isSelectionMode) {
Expand Down Expand Up @@ -139,7 +137,7 @@ fun HomeScreen(
) {
item { ChatsTitle(scrollBehavior) }
itemsIndexed(chatListState.chats, key = { _, it -> it.id }) { idx, chatRoom ->
val usingPlatform = chatRoom.enabledPlatform.joinToString(", ")
val usingPlatform = chatRoom.enabledPlatform.map { uid -> platformState.getPlatformName(uid) }.joinToString(", ")
ListItem(
modifier = Modifier
.fillMaxWidth()
Expand All @@ -162,7 +160,7 @@ fun HomeScreen(
leadingContent = {
if (chatListState.isSelectionMode) {
Checkbox(
checked = chatListState.selected[idx],
checked = chatListState.selectedChats[idx],
onCheckedChange = { homeViewModel.selectChat(idx) }
)
} else {
Expand All @@ -180,20 +178,21 @@ fun HomeScreen(
if (showSelectModelDialog) {
SelectPlatformDialog(
platformState,
selectedPlatforms = chatListState.selectedPlatforms,
onDismissRequest = { homeViewModel.closeSelectModelDialog() },
onConfirmation = {
homeViewModel.closeSelectModelDialog()
navigateToNewChat(it)
homeViewModel.closeSelectModelDialog()
},
onPlatformSelect = { homeViewModel.updateCheckedState(it) }
onPlatformSelect = { homeViewModel.updatePlatformCheckedState(it) }
)
}

if (showDeleteWarningDialog) {
DeleteWarningDialog(
onDismissRequest = homeViewModel::closeDeleteWarningDialog,
onConfirm = {
val deletedChatRoomCount = chatListState.selected.count { it }
val deletedChatRoomCount = chatListState.selectedChats.count { it }
homeViewModel.deleteSelectedChats()
Toast.makeText(context, context.getString(R.string.deleted_chats, deletedChatRoomCount), Toast.LENGTH_SHORT).show()
homeViewModel.closeDeleteWarningDialog()
Expand Down Expand Up @@ -331,12 +330,12 @@ fun NewChatButton(

@Composable
fun SelectPlatformDialog(
platforms: List<Platform>,
platforms: List<PlatformV2>,
selectedPlatforms: List<Boolean>,
onDismissRequest: () -> Unit,
onConfirmation: (enabledPlatforms: List<ApiType>) -> Unit,
onPlatformSelect: (Platform) -> Unit
onConfirmation: (enabledPlatforms: List<String>) -> Unit,
onPlatformSelect: (idx: Int) -> Unit
) {
val titles = getPlatformTitleResources()
val configuration = LocalConfiguration.current

AlertDialog(
Expand All @@ -363,13 +362,13 @@ fun SelectPlatformDialog(
HorizontalDivider()
Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
if (platforms.any { it.enabled }) {
platforms.forEach { platform ->
platforms.forEachIndexed { i, platform ->
PlatformCheckBoxItem(
platform = platform,
title = titles[platform.name]!!,
title = platform.name,
enabled = platform.enabled,
selected = selectedPlatforms[i],
description = null,
onClickEvent = { onPlatformSelect(platform) }
onClickEvent = { onPlatformSelect(i) }
)
}
} else {
Expand All @@ -380,8 +379,8 @@ fun SelectPlatformDialog(
},
confirmButton = {
TextButton(
enabled = platforms.any { it.selected },
onClick = { onConfirmation(platforms.filter { it.selected }.map { it.name }) }
enabled = selectedPlatforms.any { it },
onClick = { onConfirmation(platforms.filterIndexed { i, _ -> selectedPlatforms[i] }.map { it.uid }) }
) {
Text(stringResource(R.string.confirm))
}
Expand Down Expand Up @@ -410,24 +409,6 @@ fun EnablePlatformWarningText() {
)
}

@Preview
@Composable
private fun SelectPlatformDialogPreview() {
val platforms = listOf(
Platform(ApiType.OPENAI, enabled = true),
Platform(ApiType.ANTHROPIC, enabled = false),
Platform(ApiType.GOOGLE, enabled = false),
Platform(ApiType.GROQ, enabled = true),
Platform(ApiType.OLLAMA, enabled = true)
)
SelectPlatformDialog(
platforms = platforms,
onDismissRequest = {},
onConfirmation = {},
onPlatformSelect = {}
)
}

@Composable
fun DeleteWarningDialog(
onDismissRequest: () -> Unit,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dev.chungjungsoo.gptmobile.data.database.entity.ChatRoomV2
import dev.chungjungsoo.gptmobile.data.dto.Platform
import dev.chungjungsoo.gptmobile.data.database.entity.PlatformV2
import dev.chungjungsoo.gptmobile.data.repository.ChatRepository
import dev.chungjungsoo.gptmobile.data.repository.SettingRepository
import javax.inject.Inject
Expand All @@ -24,13 +24,14 @@ class HomeViewModel @Inject constructor(
data class ChatListState(
val chats: List<ChatRoomV2> = listOf(),
val isSelectionMode: Boolean = false,
val selected: List<Boolean> = listOf()
val selectedPlatforms: List<Boolean> = listOf(),
val selectedChats: List<Boolean> = listOf()
)

private val _chatListState = MutableStateFlow(ChatListState())
val chatListState: StateFlow<ChatListState> = _chatListState.asStateFlow()

private val _platformState = MutableStateFlow(listOf<Platform>())
private val _platformState = MutableStateFlow(listOf<PlatformV2>())
val platformState = _platformState.asStateFlow()

private val _showSelectModelDialog = MutableStateFlow(false)
Expand All @@ -39,19 +40,19 @@ class HomeViewModel @Inject constructor(
private val _showDeleteWarningDialog = MutableStateFlow(false)
val showDeleteWarningDialog: StateFlow<Boolean> = _showDeleteWarningDialog.asStateFlow()

fun updateCheckedState(platform: Platform) {
val index = _platformState.value.indexOf(platform)
fun updatePlatformCheckedState(idx: Int) {
if (idx < 0 || idx >= _chatListState.value.selectedPlatforms.size) return

if (index >= 0) {
_platformState.update {
it.mapIndexed { i, p ->
if (index == i) {
p.copy(selected = p.selected.not())
_chatListState.update {
it.copy(
selectedPlatforms = it.selectedPlatforms.mapIndexed { index, b ->
if (index == idx) {
!b
} else {
p
b
}
}
}
)
}
}

Expand All @@ -71,12 +72,13 @@ class HomeViewModel @Inject constructor(

fun closeSelectModelDialog() {
_showSelectModelDialog.update { false }
_chatListState.update { it.copy(selectedPlatforms = List(it.selectedPlatforms.size) { false }) }
}

fun deleteSelectedChats() {
viewModelScope.launch {
val selectedChats = _chatListState.value.chats.filterIndexed { index, _ ->
_chatListState.value.selected[index]
_chatListState.value.selectedChats[index]
}

chatRepository.deleteChatsV2(selectedChats)
Expand All @@ -88,7 +90,7 @@ class HomeViewModel @Inject constructor(
fun disableSelectionMode() {
_chatListState.update {
it.copy(
selected = List(it.chats.size) { false },
selectedChats = List(it.chats.size) { false },
isSelectionMode = false
)
}
Expand All @@ -105,7 +107,7 @@ class HomeViewModel @Inject constructor(
_chatListState.update {
it.copy(
chats = chats,
selected = List(chats.size) { false },
selectedChats = List(chats.size) { false },
isSelectionMode = false
)
}
Expand All @@ -116,8 +118,12 @@ class HomeViewModel @Inject constructor(

fun fetchPlatformStatus() {
viewModelScope.launch {
val platforms = settingRepository.fetchPlatforms()
val platforms = settingRepository.fetchPlatformV2s()
_platformState.update { platforms }

if (_chatListState.value.selectedPlatforms.size != platforms.size) {
_chatListState.update { it.copy(selectedPlatforms = List(platforms.size) { false }) }
}
}
}

Expand All @@ -126,7 +132,7 @@ class HomeViewModel @Inject constructor(

_chatListState.update {
it.copy(
selected = it.selected.mapIndexed { index, b ->
selectedChats = it.selectedChats.mapIndexed { index, b ->
if (index == chatRoomIdx) {
!b
} else {
Expand All @@ -136,7 +142,7 @@ class HomeViewModel @Inject constructor(
)
}

if (_chatListState.value.selected.count { it } == 0) {
if (_chatListState.value.selectedChats.count { it } == 0) {
disableSelectionMode()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import dev.chungjungsoo.gptmobile.R
import dev.chungjungsoo.gptmobile.data.dto.Platform
import dev.chungjungsoo.gptmobile.presentation.common.PlatformCheckBoxItem
import dev.chungjungsoo.gptmobile.presentation.common.PrimaryLongButton
import dev.chungjungsoo.gptmobile.presentation.common.Route
import dev.chungjungsoo.gptmobile.util.getPlatformDescriptionResources
Expand Down Expand Up @@ -100,12 +99,13 @@ fun SelectPlatform(

Column(modifier = modifier) {
platforms.forEach { platform ->
PlatformCheckBoxItem(
platform = platform,
title = titles[platform.name]!!,
description = descriptions[platform.name]!!,
onClickEvent = onClickEvent
)
// TODO(): Handle platform setup
// PlatformCheckBoxItem(
// platform = platform,
// title = titles[platform.name]!!,
// description = descriptions[platform.name]!!,
// onClickEvent = onClickEvent
// )
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package dev.chungjungsoo.gptmobile.util

import dev.chungjungsoo.gptmobile.data.database.entity.PlatformV2

fun List<PlatformV2>.getPlatformName(uid: String): String = this.find { it.uid == uid }?.name ?: "Unknown"

0 comments on commit 9a3661b

Please sign in to comment.