mirror of
https://github.com/nextcloud/talk-android
synced 2025-08-11 05:55:17 +01:00
Follow up improvements
- Added ComposePreviewUtils - Added ComposePreviewUtilsDao (both for previewing w/ dependencies) - Additional fixes Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
This commit is contained in:
parent
fdfa58dcdd
commit
fd7afccbc4
@ -33,7 +33,6 @@ import coil.decode.SvgDecoder
|
||||
import coil.memory.MemoryCache
|
||||
import coil.util.DebugLogger
|
||||
import com.nextcloud.talk.BuildConfig
|
||||
import com.nextcloud.talk.filebrowser.webdav.DavUtils
|
||||
import com.nextcloud.talk.dagger.modules.BusModule
|
||||
import com.nextcloud.talk.dagger.modules.ContextModule
|
||||
import com.nextcloud.talk.dagger.modules.DaosModule
|
||||
@ -43,6 +42,7 @@ import com.nextcloud.talk.dagger.modules.RepositoryModule
|
||||
import com.nextcloud.talk.dagger.modules.RestModule
|
||||
import com.nextcloud.talk.dagger.modules.UtilsModule
|
||||
import com.nextcloud.talk.dagger.modules.ViewModelModule
|
||||
import com.nextcloud.talk.filebrowser.webdav.DavUtils
|
||||
import com.nextcloud.talk.jobs.AccountRemovalWorker
|
||||
import com.nextcloud.talk.jobs.CapabilitiesWorker
|
||||
import com.nextcloud.talk.jobs.SignalingSettingsWorker
|
||||
|
@ -153,6 +153,7 @@ import com.nextcloud.talk.ui.PlaybackSpeed
|
||||
import com.nextcloud.talk.ui.PlaybackSpeedControl
|
||||
import com.nextcloud.talk.ui.StatusDrawable
|
||||
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet
|
||||
import com.nextcloud.talk.ui.dialog.ContextChatCompose
|
||||
import com.nextcloud.talk.ui.dialog.DateTimeCompose
|
||||
import com.nextcloud.talk.ui.dialog.FileAttachmentPreviewFragment
|
||||
import com.nextcloud.talk.ui.dialog.MessageActionsDialog
|
||||
@ -208,6 +209,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
@ -296,7 +298,33 @@ class ChatActivity :
|
||||
private val startMessageSearchForResult =
|
||||
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
executeIfResultOk(it) { intent ->
|
||||
onMessageSearchResult(intent)
|
||||
runBlocking {
|
||||
val id = intent?.getStringExtra(MessageSearchActivity.RESULT_KEY_MESSAGE_ID)
|
||||
id?.let {
|
||||
val long = id.toLong()
|
||||
val isSaved = chatViewModel.isMessageSaved(id.toLong())
|
||||
if (isSaved) {
|
||||
onMessageSearchResult(intent)
|
||||
} else {
|
||||
binding.genericComposeView.apply {
|
||||
val shouldDismiss = mutableStateOf(false)
|
||||
setContent {
|
||||
val bundle = bundleOf()
|
||||
bundle.putString(BundleKeys.KEY_CREDENTIALS, credentials!!)
|
||||
bundle.putString(BundleKeys.KEY_BASE_URL, conversationUser!!.baseUrl)
|
||||
bundle.putString(KEY_ROOM_TOKEN, roomToken)
|
||||
bundle.putString(BundleKeys.KEY_MESSAGE_ID, id)
|
||||
bundle.putString(
|
||||
BundleKeys.KEY_CONVERSATION_NAME,
|
||||
currentConversation!!.displayName
|
||||
)
|
||||
ContextChatCompose(bundle).GetDialogView(shouldDismiss, context)
|
||||
}
|
||||
}
|
||||
Log.d("Julius", "Should open something else")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,8 @@ interface ChatMessageRepository : LifecycleAwareManager {
|
||||
*/
|
||||
suspend fun getMessage(messageId: Long, bundle: Bundle): Flow<ChatMessage>
|
||||
|
||||
suspend fun checkIfMessageIsSaved(messageId: Long): Boolean
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
suspend fun sendChatMessage(
|
||||
credentials: String,
|
||||
|
@ -475,6 +475,15 @@ class OfflineFirstChatRepository @Inject constructor(
|
||||
.map(ChatMessageEntity::asModel)
|
||||
}
|
||||
|
||||
override suspend fun checkIfMessageIsSaved(messageId: Long): Boolean {
|
||||
try {
|
||||
chatDao.getChatMessageForConversation(internalConversationId, messageId)
|
||||
return true
|
||||
} catch (_: Exception) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST", "MagicNumber", "Detekt.TooGenericExceptionCaught")
|
||||
private fun getMessagesFromServer(bundle: Bundle): Pair<Int, List<ChatMessageJson>>? {
|
||||
val fieldMap = bundle.getSerializable(BundleKeys.KEY_FIELD_MAP) as HashMap<String, Int>
|
||||
|
@ -281,6 +281,10 @@ class ChatViewModel @Inject constructor(
|
||||
conversationRepository.getRoom(token)
|
||||
}
|
||||
|
||||
suspend fun isMessageSaved(messageId: Long): Boolean {
|
||||
return chatRepository.checkIfMessageIsSaved(messageId)
|
||||
}
|
||||
|
||||
fun getCapabilities(user: User, token: String, conversationModel: ConversationModel) {
|
||||
Log.d(TAG, "Remote server ${conversationModel.remoteServer}")
|
||||
if (conversationModel.remoteServer.isNullOrEmpty()) {
|
||||
|
@ -8,6 +8,7 @@
|
||||
package com.nextcloud.talk.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.util.Log
|
||||
import android.view.View.TEXT_ALIGNMENT_VIEW_START
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
@ -23,6 +24,7 @@ import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@ -46,6 +48,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
@ -68,15 +71,18 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.StrokeCap
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.emoji2.widget.EmojiTextView
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.asFlow
|
||||
import autodagger.AutoInjector
|
||||
@ -84,6 +90,8 @@ import coil.compose.AsyncImage
|
||||
import com.elyeproj.loaderviewlibrary.LoaderImageView
|
||||
import com.elyeproj.loaderviewlibrary.LoaderTextView
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.activities.MainActivity
|
||||
import com.nextcloud.talk.adapters.messages.PreviewMessageViewHolder.Companion.KEY_MIMETYPE
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||
import com.nextcloud.talk.chat.data.model.ChatMessage
|
||||
@ -99,7 +107,9 @@ import com.nextcloud.talk.models.json.opengraph.Reference
|
||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||
import com.nextcloud.talk.users.UserManager
|
||||
import com.nextcloud.talk.utils.DateUtils
|
||||
import com.nextcloud.talk.utils.DrawableUtils.getDrawableResourceIdForMimeType
|
||||
import com.nextcloud.talk.utils.message.MessageUtils
|
||||
import com.nextcloud.talk.utils.preview.ComposePreviewUtils
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import org.osmdroid.config.Configuration
|
||||
@ -116,41 +126,54 @@ import kotlin.random.Random
|
||||
@Suppress("FunctionNaming", "TooManyFunctions", "LongMethod", "StaticFieldLeak", "LargeClass")
|
||||
class ComposeChatAdapter(
|
||||
private var messagesJson: List<ChatMessageJson>? = null,
|
||||
private var messageId: String? = null
|
||||
private var messageId: String? = null,
|
||||
private val utils: ComposePreviewUtils? = null
|
||||
) {
|
||||
|
||||
interface PreviewAble {
|
||||
val viewThemeUtils: ViewThemeUtils
|
||||
val messageUtils: MessageUtils
|
||||
val contactsViewModel: ContactsViewModel
|
||||
val chatViewModel: ChatViewModel
|
||||
val context: Context
|
||||
val userManager: UserManager
|
||||
}
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
inner class ComposeChatAdapterViewModel : ViewModel() {
|
||||
inner class ComposeChatAdapterViewModel : ViewModel(), PreviewAble {
|
||||
|
||||
@Inject
|
||||
lateinit var viewThemeUtils: ViewThemeUtils
|
||||
override lateinit var viewThemeUtils: ViewThemeUtils
|
||||
|
||||
@Inject
|
||||
lateinit var messageUtils: MessageUtils
|
||||
override lateinit var messageUtils: MessageUtils
|
||||
|
||||
@Inject
|
||||
lateinit var contactsViewModel: ContactsViewModel
|
||||
override lateinit var contactsViewModel: ContactsViewModel
|
||||
|
||||
@Inject
|
||||
lateinit var chatViewModel: ChatViewModel
|
||||
override lateinit var chatViewModel: ChatViewModel
|
||||
|
||||
@Inject
|
||||
lateinit var context: Context
|
||||
override lateinit var context: Context
|
||||
|
||||
@Inject
|
||||
lateinit var userManager: UserManager
|
||||
|
||||
val items = mutableStateListOf<ChatMessage>()
|
||||
override lateinit var userManager: UserManager
|
||||
|
||||
init {
|
||||
sharedApplication!!.componentApplication.inject(this)
|
||||
sharedApplication?.componentApplication?.inject(this)
|
||||
}
|
||||
|
||||
val currentUser: User = userManager.currentUser.blockingGet()
|
||||
val colorScheme = viewThemeUtils.getColorScheme(context)
|
||||
val highEmphasisColorInt = context.resources.getColor(R.color.high_emphasis_text, null)
|
||||
}
|
||||
|
||||
inner class ComposeChatAdapterPreviewViewModel(
|
||||
override val viewThemeUtils: ViewThemeUtils,
|
||||
override val messageUtils: MessageUtils,
|
||||
override val contactsViewModel: ContactsViewModel,
|
||||
override val chatViewModel: ChatViewModel,
|
||||
override val context: Context,
|
||||
override val userManager: UserManager
|
||||
) : ViewModel(), PreviewAble
|
||||
|
||||
companion object {
|
||||
val TAG: String = ComposeChatAdapter::class.java.simpleName
|
||||
private val REGULAR_TEXT_SIZE = 16.sp
|
||||
@ -173,21 +196,48 @@ class ComposeChatAdapter(
|
||||
|
||||
private var incomingShape: RoundedCornerShape = RoundedCornerShape(2.dp, 20.dp, 20.dp, 20.dp)
|
||||
private var outgoingShape: RoundedCornerShape = RoundedCornerShape(20.dp, 2.dp, 20.dp, 20.dp)
|
||||
private val viewModel = ComposeChatAdapterViewModel()
|
||||
|
||||
val viewModel: PreviewAble =
|
||||
if (utils != null) {
|
||||
ComposeChatAdapterPreviewViewModel(
|
||||
utils.viewThemeUtils,
|
||||
utils.messageUtils,
|
||||
utils.contactsViewModel,
|
||||
utils.chatViewModel,
|
||||
utils.context,
|
||||
utils.userManager
|
||||
)
|
||||
} else {
|
||||
ComposeChatAdapterViewModel()
|
||||
}
|
||||
|
||||
val items = mutableStateListOf<ChatMessage>()
|
||||
val currentUser: User = viewModel.userManager.currentUser.blockingGet()
|
||||
val colorScheme = viewModel.viewThemeUtils.getColorScheme(viewModel.context)
|
||||
val highEmphasisColorInt = viewModel.context.resources.getColor(R.color.high_emphasis_text, null)
|
||||
|
||||
fun Context.findMainActivityOrNull(): MainActivity? {
|
||||
var context = this
|
||||
while (context is ContextWrapper) {
|
||||
if (context is MainActivity) return context
|
||||
context = context.baseContext
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun addMessages(messages: MutableList<ChatMessage>, append: Boolean) {
|
||||
if (messages.isEmpty()) return
|
||||
|
||||
val processedMessages = messages.toMutableList()
|
||||
if (viewModel.items.isNotEmpty()) {
|
||||
if (items.isNotEmpty()) {
|
||||
if (append) {
|
||||
processedMessages.add(viewModel.items.first())
|
||||
processedMessages.add(items.first())
|
||||
} else {
|
||||
processedMessages.add(viewModel.items.last())
|
||||
processedMessages.add(items.last())
|
||||
}
|
||||
}
|
||||
|
||||
if (append) viewModel.items.addAll(processedMessages) else viewModel.items.addAll(0, processedMessages)
|
||||
if (append) items.addAll(processedMessages) else items.addAll(0, processedMessages)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@ -202,7 +252,7 @@ class ComposeChatAdapter(
|
||||
modifier = Modifier.padding(16.dp)
|
||||
) {
|
||||
stickyHeader {
|
||||
if (viewModel.items.size == 0) {
|
||||
if (items.size == 0) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
@ -211,11 +261,11 @@ class ComposeChatAdapter(
|
||||
ShimmerGroup()
|
||||
}
|
||||
} else {
|
||||
val timestamp = viewModel.items[listState.firstVisibleItemIndex].timestamp
|
||||
val timestamp = items[listState.firstVisibleItemIndex].timestamp
|
||||
val dateString = formatTime(timestamp * LONG_1000)
|
||||
val color = Color(viewModel.highEmphasisColorInt)
|
||||
val color = Color(highEmphasisColorInt)
|
||||
val backgroundColor =
|
||||
viewModel.context.resources.getColor(R.color.bg_message_list_incoming_bubble, null)
|
||||
LocalContext.current.resources.getColor(R.color.bg_message_list_incoming_bubble, null)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Absolute.Center,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
@ -229,8 +279,8 @@ class ComposeChatAdapter(
|
||||
.padding(8.dp)
|
||||
.shadow(
|
||||
16.dp,
|
||||
spotColor = viewModel.colorScheme.primary,
|
||||
ambientColor = viewModel.colorScheme.primary
|
||||
spotColor = colorScheme.primary,
|
||||
ambientColor = colorScheme.primary
|
||||
)
|
||||
.background(color = Color(backgroundColor), shape = RoundedCornerShape(8.dp))
|
||||
.padding(8.dp)
|
||||
@ -240,8 +290,8 @@ class ComposeChatAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
items(viewModel.items) { message ->
|
||||
message.activeUser = viewModel.currentUser
|
||||
items(items) { message ->
|
||||
message.activeUser = currentUser
|
||||
when (val type = message.getCalculateMessageType()) {
|
||||
ChatMessage.MessageType.SYSTEM_MESSAGE -> {
|
||||
if (!message.shouldFilter()) {
|
||||
@ -284,7 +334,7 @@ class ComposeChatAdapter(
|
||||
}
|
||||
}
|
||||
|
||||
if (messageId != null && viewModel.items.size > 0) {
|
||||
if (messageId != null && items.size > 0) {
|
||||
LaunchedEffect(Dispatchers.Main) {
|
||||
delay(SCROLL_DELAY)
|
||||
val pos = searchMessages(messageId!!)
|
||||
@ -326,7 +376,7 @@ class ComposeChatAdapter(
|
||||
}
|
||||
|
||||
private fun searchMessages(searchId: String): Int {
|
||||
viewModel.items.forEachIndexed { index, message ->
|
||||
items.forEachIndexed { index, message ->
|
||||
if (message.id == searchId) return index
|
||||
}
|
||||
return -1
|
||||
@ -380,18 +430,18 @@ class ComposeChatAdapter(
|
||||
@Composable
|
||||
(RowScope.() -> Unit)
|
||||
) {
|
||||
val incoming = message.actorId != viewModel.currentUser.userId
|
||||
val incoming = message.actorId != currentUser.userId
|
||||
val color = if (incoming) {
|
||||
if (message.isDeleted) {
|
||||
viewModel.context.resources.getColor(R.color.bg_message_list_incoming_bubble_deleted, null)
|
||||
LocalContext.current.resources.getColor(R.color.bg_message_list_incoming_bubble_deleted, null)
|
||||
} else {
|
||||
viewModel.context.resources.getColor(R.color.bg_message_list_incoming_bubble, null)
|
||||
LocalContext.current.resources.getColor(R.color.bg_message_list_incoming_bubble, null)
|
||||
}
|
||||
} else {
|
||||
if (message.isDeleted) {
|
||||
ColorUtils.setAlphaComponent(viewModel.colorScheme.surfaceVariant.toArgb(), HALF_OPACITY)
|
||||
ColorUtils.setAlphaComponent(colorScheme.surfaceVariant.toArgb(), HALF_OPACITY)
|
||||
} else {
|
||||
viewModel.colorScheme.surfaceVariant.toArgb()
|
||||
colorScheme.surfaceVariant.toArgb()
|
||||
}
|
||||
}
|
||||
val shape = if (incoming) incomingShape else outgoingShape
|
||||
@ -405,7 +455,7 @@ class ComposeChatAdapter(
|
||||
if (incoming) {
|
||||
val imageUri = message.actorId?.let { viewModel.contactsViewModel.getImageUri(it, true) }
|
||||
val errorPlaceholderImage: Int = R.drawable.account_circle_96dp
|
||||
val loadedImage = loadImage(imageUri, viewModel.context, errorPlaceholderImage)
|
||||
val loadedImage = loadImage(imageUri, LocalContext.current, errorPlaceholderImage)
|
||||
AsyncImage(
|
||||
model = loadedImage,
|
||||
contentDescription = stringResource(R.string.user_avatar),
|
||||
@ -427,13 +477,13 @@ class ComposeChatAdapter(
|
||||
color = Color(color),
|
||||
shape = shape
|
||||
) {
|
||||
val timeString = DateUtils(viewModel.context).getLocalTimeStringFromTimestamp(message.timestamp)
|
||||
val timeString = DateUtils(LocalContext.current).getLocalTimeStringFromTimestamp(message.timestamp)
|
||||
val modifier = if (includePadding) Modifier.padding(8.dp, 4.dp, 8.dp, 4.dp) else Modifier
|
||||
Column(modifier = modifier) {
|
||||
if (message.parentMessageId != null && !message.isDeleted && messagesJson != null) {
|
||||
messagesJson!!
|
||||
.find { it.parentMessage?.id == message.parentMessageId }
|
||||
?.parentMessage!!.asModel().let { CommonMessageQuote(viewModel.context, it) }
|
||||
?.parentMessage!!.asModel().let { CommonMessageQuote(LocalContext.current, it) }
|
||||
}
|
||||
|
||||
if (incoming) {
|
||||
@ -470,8 +520,8 @@ class ComposeChatAdapter(
|
||||
private fun Modifier.withCustomAnimation(incoming: Boolean): Modifier {
|
||||
val infiniteTransition = rememberInfiniteTransition()
|
||||
val borderColor by infiniteTransition.animateColor(
|
||||
initialValue = viewModel.colorScheme.primary,
|
||||
targetValue = viewModel.colorScheme.background,
|
||||
initialValue = colorScheme.primary,
|
||||
targetValue = colorScheme.background,
|
||||
animationSpec = infiniteRepeatable(
|
||||
animation = tween(ANIMATED_BLINK, easing = LinearEasing),
|
||||
repeatMode = RepeatMode.Reverse
|
||||
@ -542,7 +592,7 @@ class ComposeChatAdapter(
|
||||
LoaderTextView(ctx).apply {
|
||||
layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
||||
val color = if (outgoing) {
|
||||
viewModel.colorScheme.primary.toArgb()
|
||||
colorScheme.primary.toArgb()
|
||||
} else {
|
||||
resources.getColor(R.color.nc_shimmer_default_color, null)
|
||||
}
|
||||
@ -562,7 +612,7 @@ class ComposeChatAdapter(
|
||||
@Composable
|
||||
private fun EnrichedText(message: ChatMessage) {
|
||||
AndroidView(factory = { ctx ->
|
||||
val incoming = message.actorId != viewModel.currentUser.userId
|
||||
val incoming = message.actorId != currentUser.userId
|
||||
var processedMessageText = viewModel.messageUtils.enrichChatMessageText(
|
||||
ctx,
|
||||
message,
|
||||
@ -574,7 +624,7 @@ class ComposeChatAdapter(
|
||||
ctx, viewModel.viewThemeUtils, processedMessageText!!, message, null
|
||||
)
|
||||
|
||||
androidx.emoji2.widget.EmojiTextView(ctx).apply {
|
||||
EmojiTextView(ctx).apply {
|
||||
layoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
|
||||
setLineSpacing(0F, LINE_SPACING)
|
||||
textAlignment = TEXT_ALIGNMENT_VIEW_START
|
||||
@ -592,14 +642,14 @@ class ComposeChatAdapter(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SystemMessage(message: ChatMessage) {
|
||||
fun SystemMessage(message: ChatMessage) {
|
||||
val similarMessages = sharedApplication!!.resources.getQuantityString(
|
||||
R.plurals.see_similar_system_messages,
|
||||
message.expandableChildrenAmount,
|
||||
message.expandableChildrenAmount
|
||||
)
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
val timeString = DateUtils(viewModel.context).getLocalTimeStringFromTimestamp(message.timestamp)
|
||||
val timeString = DateUtils(LocalContext.current).getLocalTimeStringFromTimestamp(message.timestamp)
|
||||
Row(horizontalArrangement = Arrangement.Absolute.Center, verticalAlignment = Alignment.CenterVertically) {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Text(
|
||||
@ -632,7 +682,7 @@ class ComposeChatAdapter(
|
||||
Text(
|
||||
text,
|
||||
fontSize = AUTHOR_TEXT_SIZE,
|
||||
color = Color(viewModel.highEmphasisColorInt)
|
||||
color = Color(highEmphasisColorInt)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -640,14 +690,15 @@ class ComposeChatAdapter(
|
||||
@Composable
|
||||
private fun ImageMessage(message: ChatMessage, state: MutableState<Boolean>) {
|
||||
val hasCaption = (message.message != "{file}")
|
||||
val incoming = message.actorId != viewModel.currentUser.userId
|
||||
val timeString = DateUtils(viewModel.context).getLocalTimeStringFromTimestamp(message.timestamp)
|
||||
val incoming = message.actorId != currentUser.userId
|
||||
val timeString = DateUtils(LocalContext.current).getLocalTimeStringFromTimestamp(message.timestamp)
|
||||
CommonMessageBody(message, includePadding = false, playAnimation = state.value) {
|
||||
Column {
|
||||
message.activeUser = viewModel.currentUser
|
||||
message.activeUser = currentUser
|
||||
val imageUri = message.imageUrl
|
||||
val errorPlaceholderImage: Int = R.drawable.ic_mimetype_image
|
||||
val loadedImage = load(imageUri, viewModel.context, errorPlaceholderImage)
|
||||
val mimetype = message.selectedIndividualHashMap!![KEY_MIMETYPE]
|
||||
val drawableResourceId = getDrawableResourceIdForMimeType(mimetype)
|
||||
val loadedImage = load(imageUri, LocalContext.current, drawableResourceId)
|
||||
|
||||
AsyncImage(
|
||||
model = loadedImage,
|
||||
@ -717,8 +768,8 @@ class ComposeChatAdapter(
|
||||
WaveformSeekBar(ctx).apply {
|
||||
setWaveData(FloatArray(DEFAULT_WAVE_SIZE) { Random.nextFloat() }) // READ ONLY for now
|
||||
setColors(
|
||||
viewModel.colorScheme.inversePrimary.toArgb(),
|
||||
viewModel.colorScheme.onPrimaryContainer.toArgb()
|
||||
colorScheme.inversePrimary.toArgb(),
|
||||
colorScheme.onPrimaryContainer.toArgb()
|
||||
)
|
||||
}
|
||||
},
|
||||
@ -793,8 +844,8 @@ class ComposeChatAdapter(
|
||||
private fun LinkMessage(message: ChatMessage, state: MutableState<Boolean>) {
|
||||
val color = colorResource(R.color.high_emphasis_text)
|
||||
viewModel.chatViewModel.getOpenGraph(
|
||||
viewModel.currentUser.getCredentials(),
|
||||
viewModel.currentUser.baseUrl!!,
|
||||
currentUser.getCredentials(),
|
||||
currentUser.baseUrl!!,
|
||||
message.extractedUrlToPreview!!
|
||||
)
|
||||
CommonMessageBody(message, playAnimation = state.value) {
|
||||
@ -828,7 +879,7 @@ class ComposeChatAdapter(
|
||||
it.link?.let { Text(it, fontSize = TIME_TEXT_SIZE) }
|
||||
it.thumb?.let {
|
||||
val errorPlaceholderImage: Int = R.drawable.ic_mimetype_image
|
||||
val loadedImage = loadImage(it, viewModel.context, errorPlaceholderImage)
|
||||
val loadedImage = loadImage(it, LocalContext.current, errorPlaceholderImage)
|
||||
AsyncImage(
|
||||
model = loadedImage,
|
||||
contentDescription = stringResource(R.string.nc_sent_an_image),
|
||||
@ -882,7 +933,7 @@ class ComposeChatAdapter(
|
||||
|
||||
if (cardName?.isNotEmpty() == true) {
|
||||
val cardDescription = String.format(
|
||||
viewModel.context.resources.getString(R.string.deck_card_description),
|
||||
LocalContext.current.resources.getString(R.string.deck_card_description),
|
||||
stackName,
|
||||
boardName
|
||||
)
|
||||
@ -899,3 +950,44 @@ class ComposeChatAdapter(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 380, heightDp = 800)
|
||||
@Composable
|
||||
fun AllMessageTypesPreview() {
|
||||
val previewUtils = ComposePreviewUtils.getInstance(LocalContext.current)
|
||||
val adapter = remember { ComposeChatAdapter(messagesJson = null, messageId = null, previewUtils) }
|
||||
|
||||
val sampleMessages = remember {
|
||||
listOf(
|
||||
// Text Messages
|
||||
ChatMessage().apply {
|
||||
jsonMessageId = 1
|
||||
actorId = "user1"
|
||||
message = "I love Nextcloud"
|
||||
timestamp = System.currentTimeMillis()
|
||||
actorDisplayName = "User1"
|
||||
messageType = ChatMessage.MessageType.REGULAR_TEXT_MESSAGE.name
|
||||
},
|
||||
ChatMessage().apply {
|
||||
jsonMessageId = 2
|
||||
actorId = "user1_id"
|
||||
message = "I love Nextcloud"
|
||||
timestamp = System.currentTimeMillis()
|
||||
actorDisplayName = "User2"
|
||||
messageType = ChatMessage.MessageType.REGULAR_TEXT_MESSAGE.name
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
LaunchedEffect(sampleMessages) { // Use LaunchedEffect or similar to update state once
|
||||
if (adapter.items.isEmpty()) { // Prevent adding multiple times on recomposition
|
||||
adapter.addMessages(sampleMessages.toMutableList(), append = false) // Add messages
|
||||
}
|
||||
}
|
||||
|
||||
MaterialTheme(colorScheme = adapter.colorScheme) { // Use the (potentially faked) color scheme
|
||||
Box(modifier = Modifier.fillMaxSize()) { // Provide a container
|
||||
adapter.GetView() // Call the main Composable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,10 @@
|
||||
|
||||
package com.nextcloud.talk.ui.dialog
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.os.Bundle
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@ -94,6 +97,15 @@ class ContextChatCompose(val bundle: Bundle) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun Context.requireActivity(): Activity {
|
||||
var context = this
|
||||
while (context is ContextWrapper) {
|
||||
if (context is Activity) return context
|
||||
context = context.baseContext
|
||||
}
|
||||
throw IllegalStateException("No activity was present but it is required.")
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun GetDialogView(
|
||||
shouldDismiss: MutableState<Boolean>,
|
||||
@ -101,9 +113,11 @@ class ContextChatCompose(val bundle: Bundle) {
|
||||
contextViewModel: ContextChatComposeViewModel = ContextChatComposeViewModel()
|
||||
) {
|
||||
if (shouldDismiss.value) {
|
||||
context.requireActivity().requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
||||
return
|
||||
}
|
||||
|
||||
context.requireActivity().requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED
|
||||
val colorScheme = contextViewModel.viewThemeUtils.getColorScheme(context)
|
||||
MaterialTheme(colorScheme) {
|
||||
Dialog(
|
||||
|
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Nextcloud Talk - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2025 Your Name <your@email.com>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.utils.preview
|
||||
|
||||
import android.content.Context
|
||||
import com.github.aurae.retrofit2.LoganSquareConverterFactory
|
||||
import com.nextcloud.android.common.ui.color.ColorUtil
|
||||
import com.nextcloud.android.common.ui.theme.MaterialSchemes
|
||||
import com.nextcloud.android.common.ui.theme.utils.AndroidViewThemeUtils
|
||||
import com.nextcloud.android.common.ui.theme.utils.AndroidXViewThemeUtils
|
||||
import com.nextcloud.android.common.ui.theme.utils.DialogViewThemeUtils
|
||||
import com.nextcloud.android.common.ui.theme.utils.MaterialViewThemeUtils
|
||||
import com.nextcloud.talk.api.NcApi
|
||||
import com.nextcloud.talk.api.NcApiCoroutines
|
||||
import com.nextcloud.talk.chat.data.ChatMessageRepository
|
||||
import com.nextcloud.talk.chat.data.io.AudioFocusRequestManager
|
||||
import com.nextcloud.talk.chat.data.io.MediaRecorderManager
|
||||
import com.nextcloud.talk.chat.data.network.ChatNetworkDataSource
|
||||
import com.nextcloud.talk.chat.data.network.OfflineFirstChatRepository
|
||||
import com.nextcloud.talk.chat.data.network.RetrofitChatNetwork
|
||||
import com.nextcloud.talk.chat.viewmodels.ChatViewModel
|
||||
import com.nextcloud.talk.contacts.ContactsRepository
|
||||
import com.nextcloud.talk.contacts.ContactsRepositoryImpl
|
||||
import com.nextcloud.talk.contacts.ContactsViewModel
|
||||
import com.nextcloud.talk.conversationlist.data.OfflineConversationsRepository
|
||||
import com.nextcloud.talk.conversationlist.data.network.ConversationsNetworkDataSource
|
||||
import com.nextcloud.talk.conversationlist.data.network.OfflineFirstConversationsRepository
|
||||
import com.nextcloud.talk.conversationlist.data.network.RetrofitConversationsNetwork
|
||||
import com.nextcloud.talk.data.database.dao.ChatBlocksDao
|
||||
import com.nextcloud.talk.data.database.dao.ChatMessagesDao
|
||||
import com.nextcloud.talk.data.database.dao.ConversationsDao
|
||||
import com.nextcloud.talk.data.network.NetworkMonitor
|
||||
import com.nextcloud.talk.data.network.NetworkMonitorImpl
|
||||
import com.nextcloud.talk.data.user.UsersDao
|
||||
import com.nextcloud.talk.data.user.UsersRepository
|
||||
import com.nextcloud.talk.data.user.UsersRepositoryImpl
|
||||
import com.nextcloud.talk.repositories.reactions.ReactionsRepository
|
||||
import com.nextcloud.talk.repositories.reactions.ReactionsRepositoryImpl
|
||||
import com.nextcloud.talk.ui.theme.MaterialSchemesProviderImpl
|
||||
import com.nextcloud.talk.ui.theme.TalkSpecificViewThemeUtils
|
||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||
import com.nextcloud.talk.users.UserManager
|
||||
import com.nextcloud.talk.utils.database.user.CurrentUserProviderImpl
|
||||
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
|
||||
import com.nextcloud.talk.utils.message.MessageUtils
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferencesImpl
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import okhttp3.OkHttpClient
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
|
||||
|
||||
/**
|
||||
* TODO - basically a reimplementation of common dependencies for use in Previewing Advanced Compose Views
|
||||
* It's a hard coded Dependency Injector
|
||||
*
|
||||
*/
|
||||
class ComposePreviewUtils private constructor(context: Context) {
|
||||
private val mContext = context
|
||||
|
||||
companion object {
|
||||
fun getInstance(context: Context) = ComposePreviewUtils(context)
|
||||
val TAG: String = ComposePreviewUtils::class.java.simpleName
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
val appPreferences: AppPreferences
|
||||
get() = AppPreferencesImpl(mContext)
|
||||
|
||||
val context: Context = mContext
|
||||
|
||||
val userRepository: UsersRepository
|
||||
get() = UsersRepositoryImpl(usersDao)
|
||||
|
||||
val userManager: UserManager
|
||||
get() = UserManager(userRepository)
|
||||
|
||||
val userProvider: CurrentUserProviderNew
|
||||
get() = CurrentUserProviderImpl(userManager)
|
||||
|
||||
val colorUtil: ColorUtil
|
||||
get() = ColorUtil(mContext)
|
||||
|
||||
val materialScheme: MaterialSchemes
|
||||
get() = MaterialSchemesProviderImpl(userProvider, colorUtil).getMaterialSchemesForCurrentUser()
|
||||
|
||||
val viewThemeUtils: ViewThemeUtils
|
||||
get() {
|
||||
val android = AndroidViewThemeUtils(materialScheme, colorUtil)
|
||||
val material = MaterialViewThemeUtils(materialScheme, colorUtil)
|
||||
val androidx = AndroidXViewThemeUtils(materialScheme, android)
|
||||
val talk = TalkSpecificViewThemeUtils(materialScheme, androidx)
|
||||
val dialog = DialogViewThemeUtils(materialScheme)
|
||||
return ViewThemeUtils(materialScheme, android, material, androidx, talk, dialog)
|
||||
}
|
||||
|
||||
val messageUtils: MessageUtils
|
||||
get() = MessageUtils(mContext)
|
||||
|
||||
val retrofit: Retrofit
|
||||
get() {
|
||||
val retrofitBuilder = Retrofit.Builder()
|
||||
.client(OkHttpClient.Builder().build())
|
||||
.baseUrl("https://nextcloud.com")
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
|
||||
.addConverterFactory(LoganSquareConverterFactory.create())
|
||||
|
||||
return retrofitBuilder.build()
|
||||
}
|
||||
|
||||
val ncApi: NcApi
|
||||
get() = retrofit.create(NcApi::class.java)
|
||||
|
||||
val ncApiCoroutines: NcApiCoroutines
|
||||
get() = retrofit.create(NcApiCoroutines::class.java)
|
||||
|
||||
val chatNetworkDataSource: ChatNetworkDataSource
|
||||
get() = RetrofitChatNetwork(ncApi, ncApiCoroutines)
|
||||
|
||||
val usersDao: UsersDao
|
||||
get() = DummyUserDaoImpl()
|
||||
|
||||
val chatMessagesDao: ChatMessagesDao
|
||||
get() = DummyChatMessagesDaoImpl()
|
||||
|
||||
val chatBlocksDao: ChatBlocksDao
|
||||
get() = DummyChatBlocksDaoImpl()
|
||||
|
||||
val conversationsDao: ConversationsDao
|
||||
get() = DummyConversationDaoImpl()
|
||||
|
||||
val networkMonitor: NetworkMonitor
|
||||
get() = NetworkMonitorImpl(mContext)
|
||||
|
||||
val chatRepository: ChatMessageRepository
|
||||
get() = OfflineFirstChatRepository(
|
||||
chatMessagesDao,
|
||||
chatBlocksDao,
|
||||
chatNetworkDataSource,
|
||||
networkMonitor,
|
||||
userProvider
|
||||
)
|
||||
|
||||
val conversationNetworkDataSource: ConversationsNetworkDataSource
|
||||
get() = RetrofitConversationsNetwork(ncApi)
|
||||
|
||||
val conversationRepository: OfflineConversationsRepository
|
||||
get() = OfflineFirstConversationsRepository(
|
||||
conversationsDao,
|
||||
conversationNetworkDataSource,
|
||||
chatNetworkDataSource,
|
||||
networkMonitor,
|
||||
userProvider
|
||||
)
|
||||
|
||||
val reactionsRepository: ReactionsRepository
|
||||
get() = ReactionsRepositoryImpl(ncApi, userProvider, chatMessagesDao)
|
||||
|
||||
val mediaRecorderManager: MediaRecorderManager
|
||||
get() = MediaRecorderManager()
|
||||
|
||||
val audioFocusRequestManager: AudioFocusRequestManager
|
||||
get() = AudioFocusRequestManager(mContext)
|
||||
|
||||
val chatViewModel: ChatViewModel
|
||||
get() = ChatViewModel(
|
||||
appPreferences,
|
||||
chatNetworkDataSource,
|
||||
chatRepository,
|
||||
conversationRepository,
|
||||
reactionsRepository,
|
||||
mediaRecorderManager,
|
||||
audioFocusRequestManager,
|
||||
userProvider
|
||||
)
|
||||
|
||||
val contactsRepository: ContactsRepository
|
||||
get() = ContactsRepositoryImpl(ncApiCoroutines, userProvider)
|
||||
|
||||
val contactsViewModel: ContactsViewModel
|
||||
get() = ContactsViewModel(contactsRepository)
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Nextcloud Talk - Android Client
|
||||
*
|
||||
* SPDX-FileCopyrightText: 2025 Your Name <your@email.com>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.utils.preview
|
||||
|
||||
import com.nextcloud.talk.data.database.dao.ChatBlocksDao
|
||||
import com.nextcloud.talk.data.database.dao.ChatMessagesDao
|
||||
import com.nextcloud.talk.data.database.dao.ConversationsDao
|
||||
import com.nextcloud.talk.data.database.model.ChatBlockEntity
|
||||
import com.nextcloud.talk.data.database.model.ChatMessageEntity
|
||||
import com.nextcloud.talk.data.database.model.ConversationEntity
|
||||
import com.nextcloud.talk.data.user.UsersDao
|
||||
import com.nextcloud.talk.data.user.model.UserEntity
|
||||
import com.nextcloud.talk.models.json.push.PushConfigurationState
|
||||
import io.reactivex.Maybe
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.Single
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
class DummyChatMessagesDaoImpl : ChatMessagesDao {
|
||||
override fun getNewestMessageId(internalConversationId: String): Long = 0L
|
||||
|
||||
override fun getMessagesForConversation(internalConversationId: String): Flow<List<ChatMessageEntity>> = flowOf()
|
||||
|
||||
override fun getTempMessagesForConversation(internalConversationId: String): Flow<List<ChatMessageEntity>> =
|
||||
flowOf()
|
||||
|
||||
override fun getTempMessageForConversation(
|
||||
internalConversationId: String,
|
||||
referenceId: String
|
||||
): Flow<ChatMessageEntity> = flowOf()
|
||||
|
||||
override suspend fun upsertChatMessages(chatMessages: List<ChatMessageEntity>) { /* */ }
|
||||
|
||||
override suspend fun upsertChatMessage(chatMessage: ChatMessageEntity) { /* */ }
|
||||
|
||||
override fun getChatMessageForConversation(
|
||||
internalConversationId: String,
|
||||
messageId: Long
|
||||
): Flow<ChatMessageEntity> = flowOf()
|
||||
|
||||
override fun deleteChatMessages(internalIds: List<String>) { /* */ }
|
||||
|
||||
override fun deleteTempChatMessages(internalConversationId: String, referenceIds: List<String>) { /* */ }
|
||||
|
||||
override fun updateChatMessage(message: ChatMessageEntity) { /* */ }
|
||||
|
||||
override fun getMessagesFromIds(messageIds: List<Long>): Flow<List<ChatMessageEntity>> = flowOf()
|
||||
|
||||
override fun getMessagesForConversationSince(
|
||||
internalConversationId: String,
|
||||
messageId: Long
|
||||
): Flow<List<ChatMessageEntity>> = flowOf()
|
||||
|
||||
override fun getMessagesForConversationBefore(
|
||||
internalConversationId: String,
|
||||
messageId: Long,
|
||||
limit: Int
|
||||
): Flow<List<ChatMessageEntity>> = flowOf()
|
||||
|
||||
override fun getMessagesForConversationBeforeAndEqual(
|
||||
internalConversationId: String,
|
||||
messageId: Long,
|
||||
limit: Int
|
||||
): Flow<List<ChatMessageEntity>> = flowOf()
|
||||
|
||||
override fun getCountBetweenMessageIds(
|
||||
internalConversationId: String,
|
||||
oldestMessageId: Long,
|
||||
newestMessageId: Long
|
||||
): Int = 0
|
||||
|
||||
override fun clearAllMessagesForUser(pattern: String) { /* */ }
|
||||
|
||||
override fun deleteMessagesOlderThan(internalConversationId: String, messageId: Long) { /* */ }
|
||||
}
|
||||
|
||||
class DummyUserDaoImpl : UsersDao() {
|
||||
private val dummyUsers = mutableListOf(
|
||||
UserEntity(1L, "user1_id", "user1", "server1", "1"),
|
||||
UserEntity(2L, "user2_id", "user2", "server1", "2"),
|
||||
UserEntity(0L, "user3_id", "user3", "server2", "3")
|
||||
)
|
||||
private var activeUserId: Long? = 1L
|
||||
|
||||
override fun getActiveUser(): Maybe<UserEntity> {
|
||||
return Maybe.fromCallable { dummyUsers.find { it.id == activeUserId && !it.scheduledForDeletion } }
|
||||
}
|
||||
|
||||
override fun getActiveUserObservable(): Observable<UserEntity> {
|
||||
return Observable.fromCallable { dummyUsers.find { it.id == activeUserId && !it.scheduledForDeletion } }
|
||||
}
|
||||
|
||||
override fun getActiveUserSynchronously(): UserEntity? {
|
||||
return dummyUsers.find { it.id == activeUserId && !it.scheduledForDeletion }
|
||||
}
|
||||
|
||||
override fun deleteUser(user: UserEntity): Int {
|
||||
val initialSize = dummyUsers.size
|
||||
dummyUsers.removeIf { it.id == user.id }
|
||||
return initialSize - dummyUsers.size
|
||||
}
|
||||
|
||||
override fun updateUser(user: UserEntity): Int {
|
||||
val index = dummyUsers.indexOfFirst { it.id == user.id }
|
||||
return if (index != -1) {
|
||||
dummyUsers[index] = user
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveUser(user: UserEntity): Long {
|
||||
val newUser = user.copy(id = dummyUsers.size + 1L)
|
||||
dummyUsers.add(newUser)
|
||||
return newUser.id
|
||||
}
|
||||
|
||||
override fun saveUsers(vararg users: UserEntity): List<Long> {
|
||||
return users.map { saveUser(it) }
|
||||
}
|
||||
|
||||
override fun getUsers(): Single<List<UserEntity>> {
|
||||
return Single.just(dummyUsers.filter { !it.scheduledForDeletion })
|
||||
}
|
||||
|
||||
override fun getUserWithId(id: Long): Maybe<UserEntity> {
|
||||
return Maybe.fromCallable { dummyUsers.find { it.id == id } }
|
||||
}
|
||||
|
||||
override fun getUserWithIdNotScheduledForDeletion(id: Long): Maybe<UserEntity> {
|
||||
return Maybe.fromCallable { dummyUsers.find { it.id == id && !it.scheduledForDeletion } }
|
||||
}
|
||||
|
||||
override fun getUserWithUserId(userId: String): Maybe<UserEntity> {
|
||||
return Maybe.fromCallable { dummyUsers.find { it.userId == userId } }
|
||||
}
|
||||
|
||||
override fun getUsersScheduledForDeletion(): Single<List<UserEntity>> {
|
||||
return Single.just(dummyUsers.filter { it.scheduledForDeletion })
|
||||
}
|
||||
|
||||
override fun getUsersNotScheduledForDeletion(): Single<List<UserEntity>> {
|
||||
return Single.just(dummyUsers.filter { !it.scheduledForDeletion })
|
||||
}
|
||||
|
||||
override fun getUserWithUsernameAndServer(username: String, server: String): Maybe<UserEntity> {
|
||||
return Maybe.fromCallable { dummyUsers.find { it.username == username } }
|
||||
}
|
||||
|
||||
override fun setUserAsActiveWithId(id: Long): Int {
|
||||
activeUserId = id
|
||||
return 1
|
||||
}
|
||||
|
||||
override fun updatePushState(id: Long, state: PushConfigurationState): Single<Int> {
|
||||
val index = dummyUsers.indexOfFirst { it.id == id }
|
||||
return if (index != -1) {
|
||||
dummyUsers[index] = dummyUsers[index]
|
||||
Single.just(1)
|
||||
} else {
|
||||
Single.just(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DummyConversationDaoImpl : ConversationsDao {
|
||||
override fun getConversationsForUser(accountId: Long): Flow<List<ConversationEntity>> = flowOf()
|
||||
|
||||
override fun getConversationForUser(accountId: Long, token: String): Flow<ConversationEntity?> = flowOf()
|
||||
|
||||
override fun upsertConversations(conversationEntities: List<ConversationEntity>) { /* */ }
|
||||
|
||||
override fun deleteConversations(conversationIds: List<String>) { /* */ }
|
||||
|
||||
override fun updateConversation(conversationEntity: ConversationEntity) { /* */ }
|
||||
|
||||
override fun clearAllConversationsForUser(accountId: Long) { /* */ }
|
||||
}
|
||||
|
||||
class DummyChatBlocksDaoImpl : ChatBlocksDao {
|
||||
override fun deleteChatBlocks(blocks: List<ChatBlockEntity>) { /* */ }
|
||||
|
||||
override fun getChatBlocks(internalConversationId: String): Flow<List<ChatBlockEntity>> = flowOf()
|
||||
|
||||
override fun getChatBlocksContainingMessageId(
|
||||
internalConversationId: String,
|
||||
messageId: Long
|
||||
): Flow<List<ChatBlockEntity?>> = flowOf()
|
||||
|
||||
override fun getConnectedChatBlocks(
|
||||
internalConversationId: String,
|
||||
oldestMessageId: Long,
|
||||
newestMessageId: Long
|
||||
): Flow<List<ChatBlockEntity>> = flowOf()
|
||||
|
||||
override suspend fun upsertChatBlock(chatBlock: ChatBlockEntity) { /* */ }
|
||||
|
||||
override fun clearChatBlocksForUser(pattern: String) { /* */ }
|
||||
|
||||
override fun deleteChatBlocksOlderThan(internalConversationId: String, messageId: Long) { /* */ }
|
||||
}
|
Loading…
Reference in New Issue
Block a user