Improve various UI for chat folders.

This commit is contained in:
Michelle Tang
2024-10-25 15:42:05 -04:00
committed by GitHub
parent 310c7bd98e
commit 83808ed427
11 changed files with 84 additions and 41 deletions

View File

@@ -71,7 +71,8 @@ class AppSettingsActivity : DSLSettingsActivity(), InAppPaymentComponent {
StartLocation.REMOTE_BACKUPS -> AppSettingsFragmentDirections.actionDirectToRemoteBackupsSettingsFragment()
StartLocation.CHAT_FOLDERS -> AppSettingsFragmentDirections.actionDirectToChatFoldersFragment()
StartLocation.CREATE_CHAT_FOLDER -> AppSettingsFragmentDirections.actionDirectToCreateFoldersFragment(
CreateFoldersFragmentArgs.fromBundle(intent.getBundleExtra(START_ARGUMENTS)!!).folderId
CreateFoldersFragmentArgs.fromBundle(intent.getBundleExtra(START_ARGUMENTS)!!).folderId,
CreateFoldersFragmentArgs.fromBundle(intent.getBundleExtra(START_ARGUMENTS)!!).threadId
)
}
}
@@ -207,8 +208,8 @@ class AppSettingsActivity : DSLSettingsActivity(), InAppPaymentComponent {
fun chatFolders(context: Context): Intent = getIntentForStartLocation(context, StartLocation.CHAT_FOLDERS)
@JvmStatic
fun createChatFolder(context: Context, id: Long = -1): Intent {
val arguments = CreateFoldersFragmentArgs.Builder(id)
fun createChatFolder(context: Context, id: Long = -1, threadId: Long?): Intent {
val arguments = CreateFoldersFragmentArgs.Builder(id, threadId ?: -1)
.build()
.toBundle()

View File

@@ -84,7 +84,7 @@ class ChatFoldersFragment : ComposeFragment() {
navController = navController,
modifier = Modifier.padding(contentPadding),
onFolderClicked = {
navController.safeNavigate(ChatFoldersFragmentDirections.actionChatFoldersFragmentToCreateFoldersFragment(it.id))
navController.safeNavigate(ChatFoldersFragmentDirections.actionChatFoldersFragmentToCreateFoldersFragment(it.id, -1))
},
onAdd = { folder ->
Toast.makeText(requireContext(), getString(R.string.ChatFoldersFragment__folder_added, folder.name), Toast.LENGTH_SHORT).show()

View File

@@ -225,6 +225,25 @@ class ChatFoldersViewModel : ViewModel() {
}
}
fun addThreadToIncludedChat(threadId: Long?) {
if (threadId == null || threadId == -1L) {
return
}
viewModelScope.launch {
val updatedFolder = internalState.value.currentFolder
val recipient = SignalDatabase.threads.getRecipientForThreadId(threadId)
if (recipient != null) {
internalState.update {
it.copy(
currentFolder = updatedFolder.copy(
includedRecipients = setOf(recipient)
)
)
}
}
}
}
fun addIncludedChat(recipientId: RecipientId) {
val includedChats = internalState.value.pendingIncludedRecipients.plus(recipientId)
internalState.update {
@@ -325,4 +344,8 @@ class ChatFoldersViewModel : ViewModel() {
}
}
}
fun hasEmptyName(): Boolean {
return state.value.currentFolder.name.isEmpty()
}
}

View File

@@ -20,6 +20,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.ButtonDefaults
@@ -44,6 +45,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.unit.dp
import androidx.fragment.app.activityViewModels
import androidx.navigation.NavController
@@ -57,6 +59,7 @@ import org.signal.core.ui.SignalPreview
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.avatar.AvatarImage
import org.thoughtcrime.securesms.compose.ComposeFragment
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.util.navigation.safeNavigate
@@ -76,7 +79,7 @@ class CreateFoldersFragment : ComposeFragment() {
viewLifecycleOwner,
object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (viewModel.hasChanges()) {
if (viewModel.hasChanges() && !viewModel.hasEmptyName()) {
viewModel.showConfirmationDialog(true)
} else {
findNavController().popBackStack()
@@ -96,13 +99,21 @@ class CreateFoldersFragment : ComposeFragment() {
LaunchedEffect(Unit) {
if (state.originalFolder == state.currentFolder) {
viewModel.setCurrentFolderId(arguments?.getLong(KEY_FOLDER_ID) ?: -1)
viewModel.addThreadToIncludedChat(arguments?.getLong(KEY_THREAD_ID))
}
}
LaunchedEffect(Unit) {
if (!SignalStore.uiHints.hasSeenChatFoldersEducationSheet) {
SignalStore.uiHints.hasSeenChatFoldersEducationSheet = true
navController.safeNavigate(R.id.action_createFoldersFragment_to_chatFoldersEducationSheet)
}
}
Scaffolds.Settings(
title = if (isNewFolder) stringResource(id = R.string.CreateFoldersFragment__create_a_folder) else stringResource(id = R.string.CreateFoldersFragment__edit_folder),
onNavigationClick = {
if (viewModel.hasChanges()) {
if (viewModel.hasChanges() && !viewModel.hasEmptyName()) {
viewModel.showConfirmationDialog(true)
} else {
navController.popBackStack()
@@ -161,6 +172,7 @@ class CreateFoldersFragment : ComposeFragment() {
companion object {
private val KEY_FOLDER_ID = "folder_id"
private val KEY_THREAD_ID = "thread_id"
}
}
@@ -195,24 +207,14 @@ fun CreateFolderScreen(
dismiss = stringResource(id = android.R.string.cancel),
onDismiss = onDeleteDismissed
)
} else if (state.showConfirmationDialog && isNewFolder) {
Dialogs.SimpleAlertDialog(
title = stringResource(id = R.string.CreateFoldersFragment__create_folder_title),
body = stringResource(id = R.string.CreateFoldersFragment__do_you_want_to_create, state.currentFolder.name),
confirm = stringResource(id = R.string.CreateFoldersFragment__create_folder),
onConfirm = { onCreateConfirmed(false) },
dismiss = stringResource(id = R.string.CreateFoldersFragment__discard),
onDismiss = { onCreateDismissed(true) },
onDismissRequest = { onCreateDismissed(false) }
)
} else if (state.showConfirmationDialog) {
Dialogs.SimpleAlertDialog(
title = stringResource(id = R.string.CreateFoldersFragment__save_changes_title),
body = stringResource(id = R.string.CreateFoldersFragment__do_you_want_to_save),
confirm = stringResource(id = R.string.CreateFoldersFragment__save_changes),
onConfirm = { onCreateConfirmed(false) },
dismiss = stringResource(id = R.string.CreateFoldersFragment__discard),
onDismiss = { onCreateDismissed(true) },
title = stringResource(id = R.string.CreateFoldersFragment__discard_changes_title),
body = stringResource(id = R.string.CreateFoldersFragment__you_will_lose_changes),
confirm = stringResource(id = R.string.CreateFoldersFragment__discard),
onConfirm = { onCreateDismissed(true) },
dismiss = stringResource(id = android.R.string.cancel),
onDismiss = { onCreateDismissed(false) },
onDismissRequest = { onCreateDismissed(false) }
)
}
@@ -224,6 +226,7 @@ fun CreateFolderScreen(
value = state.currentFolder.name,
label = { Text(text = stringResource(id = R.string.CreateFoldersFragment__folder_name)) },
onValueChange = onNameChange,
keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences),
singleLine = true,
modifier = modifier
.fillMaxWidth()

View File

@@ -77,7 +77,7 @@ class AddToFolderBottomSheet private constructor() : ComposeBottomSheetDialogFra
dismissAllowingStateLoss()
},
onCreate = {
requireContext().startActivity(AppSettingsActivity.createChatFolder(requireContext(), -1))
requireContext().startActivity(AppSettingsActivity.createChatFolder(requireContext(), -1, threadId))
dismissAllowingStateLoss()
}
)

View File

@@ -53,7 +53,11 @@ class ChatFolderAdapter(val callbacks: Callbacks) : MappingAdapter() {
true
}
if (model.isSelected) {
itemView.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(itemView.context, R.color.signal_colorSurface2))
itemView.backgroundTintList = if (callbacks.isScrolled()) {
ColorStateList.valueOf(ContextCompat.getColor(itemView.context, R.color.signal_colorBackground))
} else {
ColorStateList.valueOf(ContextCompat.getColor(itemView.context, R.color.signal_colorSurface2))
}
} else {
itemView.backgroundTintList = ColorStateList.valueOf(ContextCompat.getColor(itemView.context, R.color.transparent))
}
@@ -75,5 +79,6 @@ class ChatFolderAdapter(val callbacks: Callbacks) : MappingAdapter() {
fun onUnmuteAll(chatFolder: ChatFolderRecord)
fun onReadAll(chatFolder: ChatFolderRecord)
fun onFolderSettings()
fun isScrolled(): Boolean
}
}

View File

@@ -1485,12 +1485,12 @@ public class ConversationListFragment extends MainFragment implements ActionMode
if (conversation.getThreadRecord().isArchived()) {
items.add(new ActionItem(R.drawable.symbol_archive_up_24, getResources().getString(R.string.ConversationListFragment_unarchive), () -> handleArchive(id, false)));
} else {
if (RemoteConfig.internalUser() && viewModel.getCurrentFolder().getFolderType() == ChatFolderRecord.FolderType.ALL) {
if (viewModel.getCurrentFolder().getFolderType() == ChatFolderRecord.FolderType.ALL) {
List<ChatFolderRecord> folders = viewModel.getFolders().stream().map(ChatFolderMappingModel::getChatFolder).collect(Collectors.toList());
items.add(new ActionItem(R.drawable.symbol_folder_add, getString(R.string.ConversationListFragment_add_to_folder), () ->
AddToFolderBottomSheet.showChatFolderSheet(folders, conversation.getThreadRecord().getThreadId()).show(getParentFragmentManager(), BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
));
} else if (RemoteConfig.internalUser()){
} else {
items.add(new ActionItem(R.drawable.symbol_folder_minus, getString(R.string.ConversationListFragment_remove_from_folder), () -> viewModel.removeChatFromFolder(conversation.getThreadRecord().getThreadId())));
}
items.add(new ActionItem(R.drawable.symbol_archive_24, getResources().getString(R.string.ConversationListFragment_archive), () -> handleArchive(id, false)));
@@ -1689,6 +1689,11 @@ public class ConversationListFragment extends MainFragment implements ActionMode
pullViewAppBarLayout.setExpanded(false, true);
}
@Override
public boolean isScrolled() {
return list.canScrollVertically(-1);
}
@Override
public void onChatFolderClicked(@NonNull ChatFolderRecord chatFolder) {
int oldIndex = -1;
@@ -1724,7 +1729,7 @@ public class ConversationListFragment extends MainFragment implements ActionMode
@Override
public void onEdit(@NonNull ChatFolderRecord chatFolder) {
startActivity(AppSettingsActivity.createChatFolder(requireContext(), chatFolder.getId()));
startActivity(AppSettingsActivity.createChatFolder(requireContext(), chatFolder.getId(), null));
}
@Override

View File

@@ -143,7 +143,9 @@ class ConversationListViewModel(
if (conversations.isNotEmpty()) {
false
} else {
SignalDatabase.threads.getArchivedConversationListCount(filterRequest.filter) == 0
val archivedCount = SignalDatabase.threads.getArchivedConversationListCount(filterRequest.filter)
val unarchivedCount = SignalDatabase.threads.getUnarchivedConversationListCount(filterRequest.filter)
(archivedCount + unarchivedCount) == 0
}
}
.observeOn(AndroidSchedulers.mainThread())