mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-14 16:25:05 +01:00
Serious fixes to loading mechanism
This commit is contained in:
parent
f311aa1d16
commit
3767b7fd61
@ -48,7 +48,7 @@ import java.util.regex.Pattern
|
|||||||
|
|
||||||
class ConversationItem(
|
class ConversationItem(
|
||||||
val model: Conversation,
|
val model: Conversation,
|
||||||
private val user: UserNgEntity,
|
val user: UserNgEntity,
|
||||||
private val context: Context
|
private val context: Context
|
||||||
) : AbstractFlexibleItem<ConversationItem.ConversationItemViewHolder>(), IFilterable<String> {
|
) : AbstractFlexibleItem<ConversationItem.ConversationItemViewHolder>(), IFilterable<String> {
|
||||||
|
|
||||||
@ -56,6 +56,7 @@ class ConversationItem(
|
|||||||
if (other is ConversationItem) {
|
if (other is ConversationItem) {
|
||||||
val inItem = other as ConversationItem?
|
val inItem = other as ConversationItem?
|
||||||
val comparedConversation = inItem!!.model
|
val comparedConversation = inItem!!.model
|
||||||
|
|
||||||
return (model.conversationId == comparedConversation.conversationId
|
return (model.conversationId == comparedConversation.conversationId
|
||||||
&& model.token == comparedConversation.token
|
&& model.token == comparedConversation.token
|
||||||
&& model.name == comparedConversation.name
|
&& model.name == comparedConversation.name
|
||||||
@ -68,7 +69,7 @@ class ConversationItem(
|
|||||||
&& model.unreadMention == comparedConversation.unreadMention
|
&& model.unreadMention == comparedConversation.unreadMention
|
||||||
&& model.objectType == comparedConversation.objectType
|
&& model.objectType == comparedConversation.objectType
|
||||||
&& model.changing == comparedConversation.changing
|
&& model.changing == comparedConversation.changing
|
||||||
&& inItem.user.id == other.user.id)
|
&& inItem.user.id == user.id)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -199,7 +200,6 @@ class ConversationItem(
|
|||||||
|
|
||||||
holder.itemView.dialogAvatar.visibility = View.VISIBLE
|
holder.itemView.dialogAvatar.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
|
||||||
val conversationDrawable: Drawable? = Images().getImageForConversation(context, model)
|
val conversationDrawable: Drawable? = Images().getImageForConversation(context, model)
|
||||||
if (conversationDrawable != null) {
|
if (conversationDrawable != null) {
|
||||||
holder.itemView.dialogAvatar.load(conversationDrawable)
|
holder.itemView.dialogAvatar.load(conversationDrawable)
|
||||||
|
@ -220,7 +220,7 @@ class MagicIncomingTextMessageViewHolder(incomingView: View) : MessageHolders
|
|||||||
message.parentMessage?.let { parentChatMessage ->
|
message.parentMessage?.let { parentChatMessage ->
|
||||||
parentChatMessage.activeUser = message.activeUser
|
parentChatMessage.activeUser = message.activeUser
|
||||||
imageLoader.loadImage(quotedUserAvatar, parentChatMessage.user.avatar, null)
|
imageLoader.loadImage(quotedUserAvatar, parentChatMessage.user.avatar, null)
|
||||||
parentChatMessage.imageUrl?.let{
|
parentChatMessage.imageUrl?.let {
|
||||||
quotedMessagePreview?.visibility = View.VISIBLE
|
quotedMessagePreview?.visibility = View.VISIBLE
|
||||||
imageLoader.loadImage(quotedMessagePreview, it, null)
|
imageLoader.loadImage(quotedMessagePreview, it, null)
|
||||||
} ?: run {
|
} ?: run {
|
||||||
|
@ -24,7 +24,6 @@ import android.content.Intent
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.text.Spannable
|
import android.text.Spannable
|
||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
import android.util.Log
|
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
@ -146,7 +145,7 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
|
|||||||
message.parentMessage?.let { parentChatMessage ->
|
message.parentMessage?.let { parentChatMessage ->
|
||||||
parentChatMessage.activeUser = message.activeUser
|
parentChatMessage.activeUser = message.activeUser
|
||||||
imageLoader.loadImage(quotedUserAvatar, parentChatMessage.user.avatar, null)
|
imageLoader.loadImage(quotedUserAvatar, parentChatMessage.user.avatar, null)
|
||||||
parentChatMessage.imageUrl?.let{
|
parentChatMessage.imageUrl?.let {
|
||||||
quotedMessagePreview?.visibility = View.VISIBLE
|
quotedMessagePreview?.visibility = View.VISIBLE
|
||||||
imageLoader.loadImage(quotedMessagePreview, it, null)
|
imageLoader.loadImage(quotedMessagePreview, it, null)
|
||||||
} ?: run {
|
} ?: run {
|
||||||
|
@ -393,7 +393,7 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
|||||||
messagesListView?.setAdapter(adapter)
|
messagesListView?.setAdapter(adapter)
|
||||||
adapter?.setLoadMoreListener(this)
|
adapter?.setLoadMoreListener(this)
|
||||||
adapter?.setDateHeadersFormatter { format(it) }
|
adapter?.setDateHeadersFormatter { format(it) }
|
||||||
adapter?.setOnMessageViewLongClickListener { view, message -> onMessageViewLongClick(view, message)}
|
adapter?.setOnMessageViewLongClickListener { view, message -> onMessageViewLongClick(view, message) }
|
||||||
|
|
||||||
layoutManager = messagesListView?.layoutManager as LinearLayoutManager?
|
layoutManager = messagesListView?.layoutManager as LinearLayoutManager?
|
||||||
|
|
||||||
@ -931,7 +931,7 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
|||||||
|
|
||||||
messageInput?.setText("")
|
messageInput?.setText("")
|
||||||
val replyMessageId: Long? = view?.findViewById<RelativeLayout>(R.id.quotedChatMessageView)?.tag as Long?
|
val replyMessageId: Long? = view?.findViewById<RelativeLayout>(R.id.quotedChatMessageView)?.tag as Long?
|
||||||
sendMessage(editable, if (view?.findViewById<RelativeLayout>(R.id.quotedChatMessageView)?.visibility == View.VISIBLE) replyMessageId?.toInt() else null )
|
sendMessage(editable, if (view?.findViewById<RelativeLayout>(R.id.quotedChatMessageView)?.visibility == View.VISIBLE) replyMessageId?.toInt() else null)
|
||||||
cancelReply()
|
cancelReply()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1412,7 +1412,8 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
|||||||
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.ellipsize = TextUtils.TruncateAt.END
|
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.ellipsize = TextUtils.TruncateAt.END
|
||||||
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.text = it.text
|
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.text = it.text
|
||||||
messageInputView?.findViewById<TextView>(R.id.quotedMessageTime)?.text = DateFormatter.format(it.createdAt, DateFormatter.Template.TIME)
|
messageInputView?.findViewById<TextView>(R.id.quotedMessageTime)?.text = DateFormatter.format(it.createdAt, DateFormatter.Template.TIME)
|
||||||
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessageAuthor)?.text = it.actorDisplayName ?: context.getText(R.string.nc_nick_guest)
|
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessageAuthor)?.text = it.actorDisplayName
|
||||||
|
?: context.getText(R.string.nc_nick_guest)
|
||||||
|
|
||||||
conversationUser?.let { currentUser ->
|
conversationUser?.let { currentUser ->
|
||||||
messageInputView?.findViewById<ImageView>(R.id.quotedUserAvatar)?.load(it.user.avatar) {
|
messageInputView?.findViewById<ImageView>(R.id.quotedUserAvatar)?.load(it.user.avatar) {
|
||||||
@ -1420,7 +1421,7 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
|||||||
transformations(CircleCropTransformation())
|
transformations(CircleCropTransformation())
|
||||||
}
|
}
|
||||||
|
|
||||||
chatMessage.imageUrl?.let{ previewImageUrl ->
|
chatMessage.imageUrl?.let { previewImageUrl ->
|
||||||
messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)?.visibility = View.VISIBLE
|
messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)?.visibility = View.VISIBLE
|
||||||
|
|
||||||
val px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 96f, resources?.displayMetrics)
|
val px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 96f, resources?.displayMetrics)
|
||||||
|
@ -21,8 +21,6 @@
|
|||||||
package com.nextcloud.talk.controllers
|
package com.nextcloud.talk.controllers
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.LayerDrawable
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@ -61,7 +59,8 @@ import com.nextcloud.talk.jobs.DeleteConversationWorker
|
|||||||
import com.nextcloud.talk.jobs.LeaveConversationWorker
|
import com.nextcloud.talk.jobs.LeaveConversationWorker
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType
|
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType.*
|
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType.PUBLIC_CONVERSATION
|
||||||
|
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType.SYSTEM_CONVERSATION
|
||||||
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||||
import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter
|
import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter
|
||||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||||
|
@ -297,7 +297,7 @@ class SettingsController : BaseController() {
|
|||||||
var hasMultipleUsers = false
|
var hasMultipleUsers = false
|
||||||
val job = async {
|
val job = async {
|
||||||
currentUser = usersRepository.getActiveUser()
|
currentUser = usersRepository.getActiveUser()
|
||||||
hasMultipleUsers = usersRepository.getUsers().size > 0
|
hasMultipleUsers = usersRepository.getUsers().isNotEmpty()
|
||||||
credentials = currentUser!!.getCredentials()
|
credentials = currentUser!!.getCredentials()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import com.bluelinelabs.logansquare.annotation.JsonObject
|
|||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
import lombok.Data
|
import lombok.Data
|
||||||
import org.parceler.Parcel
|
import org.parceler.Parcel
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Parcel
|
@Parcel
|
||||||
@ -44,14 +45,15 @@ data class ExternalSignalingServer(
|
|||||||
other as ExternalSignalingServer
|
other as ExternalSignalingServer
|
||||||
|
|
||||||
if (externalSignalingServer != other.externalSignalingServer) return false
|
if (externalSignalingServer != other.externalSignalingServer) return false
|
||||||
if (externalSignalingTicket != other.externalSignalingTicket) return false
|
//if (externalSignalingTicket != other.externalSignalingTicket) return false
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
var result = externalSignalingServer?.hashCode() ?: 0
|
return Objects.hash(externalSignalingServer)
|
||||||
|
/*var result = externalSignalingServer?.hashCode() ?: 0
|
||||||
result = 31 * result + (externalSignalingTicket?.hashCode() ?: 0)
|
result = 31 * result + (externalSignalingTicket?.hashCode() ?: 0)
|
||||||
return result
|
return result*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ data class Capabilities(
|
|||||||
override fun equals(o: Any?): Boolean {
|
override fun equals(o: Any?): Boolean {
|
||||||
if (this === o) return true
|
if (this === o) return true
|
||||||
if (o !is Capabilities) return false
|
if (o !is Capabilities) return false
|
||||||
|
|
||||||
return (spreedCapability == o.spreedCapability &&
|
return (spreedCapability == o.spreedCapability &&
|
||||||
notificationsCapability == o.notificationsCapability &&
|
notificationsCapability == o.notificationsCapability &&
|
||||||
themingCapability == o.themingCapability)
|
themingCapability == o.themingCapability)
|
||||||
|
@ -41,9 +41,8 @@ data class SpreedCapability(
|
|||||||
override fun equals(o: Any?): Boolean {
|
override fun equals(o: Any?): Boolean {
|
||||||
if (this === o) return true
|
if (this === o) return true
|
||||||
if (o !is SpreedCapability) return false
|
if (o !is SpreedCapability) return false
|
||||||
val that = o
|
return features == o.features &&
|
||||||
return features == that.features &&
|
config == o.config
|
||||||
config == that.config
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
|
@ -44,6 +44,7 @@ import java.util.Date;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@ -97,13 +98,35 @@ public class ChatMessage implements IMessage, MessageContentType, MessageContent
|
|||||||
public boolean replyable;
|
public boolean replyable;
|
||||||
@JsonField(name = "parent")
|
@JsonField(name = "parent")
|
||||||
public ChatMessage parentMessage;
|
public ChatMessage parentMessage;
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
@Ignore
|
@Ignore
|
||||||
List<MessageType> messageTypesToIgnore = Arrays.asList(MessageType.REGULAR_TEXT_MESSAGE,
|
List<MessageType> messageTypesToIgnore = Arrays.asList(MessageType.REGULAR_TEXT_MESSAGE,
|
||||||
MessageType.SYSTEM_MESSAGE, MessageType.SINGLE_LINK_VIDEO_MESSAGE,
|
MessageType.SYSTEM_MESSAGE, MessageType.SINGLE_LINK_VIDEO_MESSAGE,
|
||||||
MessageType.SINGLE_LINK_AUDIO_MESSAGE, MessageType.SINGLE_LINK_MESSAGE);
|
MessageType.SINGLE_LINK_AUDIO_MESSAGE, MessageType.SINGLE_LINK_MESSAGE);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof ChatMessage)) return false;
|
||||||
|
ChatMessage that = (ChatMessage) o;
|
||||||
|
return timestamp == that.timestamp &&
|
||||||
|
replyable == that.replyable &&
|
||||||
|
Objects.equals(jsonMessageId, that.jsonMessageId) &&
|
||||||
|
Objects.equals(actorType, that.actorType) &&
|
||||||
|
Objects.equals(actorId, that.actorId) &&
|
||||||
|
Objects.equals(actorDisplayName, that.actorDisplayName) &&
|
||||||
|
Objects.equals(token, that.token) &&
|
||||||
|
Objects.equals(message, that.message) &&
|
||||||
|
Objects.equals(messageParameters, that.messageParameters) &&
|
||||||
|
systemMessageType == that.systemMessageType &&
|
||||||
|
Objects.equals(parentMessage, that.parentMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(jsonMessageId, token, actorType, actorId, actorDisplayName, timestamp, message, messageParameters, systemMessageType, replyable, parentMessage);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean hasFileAttachment() {
|
private boolean hasFileAttachment() {
|
||||||
if (messageParameters != null && messageParameters.size() > 0) {
|
if (messageParameters != null && messageParameters.size() > 0) {
|
||||||
for (String key : messageParameters.keySet()) {
|
for (String key : messageParameters.keySet()) {
|
||||||
|
@ -22,15 +22,15 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.models.json.converters
|
package com.nextcloud.talk.models.json.converters
|
||||||
|
|
||||||
import com.bluelinelabs.logansquare.typeconverters.LongBasedTypeConverter
|
import com.bluelinelabs.logansquare.typeconverters.IntBasedTypeConverter
|
||||||
import com.nextcloud.talk.models.json.participants.Participant
|
import com.nextcloud.talk.models.json.participants.Participant
|
||||||
|
|
||||||
class EnumParticipantFlagsConverter : LongBasedTypeConverter<Participant.ParticipantFlags>() {
|
class EnumParticipantFlagsConverter : IntBasedTypeConverter<Participant.ParticipantFlags>() {
|
||||||
override fun getFromLong(l: Long): Participant.ParticipantFlags {
|
override fun getFromInt(l: Int): Participant.ParticipantFlags {
|
||||||
return Participant.ParticipantFlags.fromValue(l)
|
return Participant.ParticipantFlags.fromValue(l)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun convertToLong(`object`: Participant.ParticipantFlags?): Long {
|
override fun convertToInt(`object`: Participant.ParticipantFlags?): Int {
|
||||||
return `object`?.value ?: 0
|
return `object`?.value ?: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,8 @@ import com.nextcloud.talk.models.json.converters.EnumParticipantTypeConverter;
|
|||||||
|
|
||||||
import org.parceler.Parcel;
|
import org.parceler.Parcel;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
@Parcel
|
@Parcel
|
||||||
@ -47,8 +49,8 @@ public class Participant {
|
|||||||
@JsonField(name = "displayName")
|
@JsonField(name = "displayName")
|
||||||
public String displayName;
|
public String displayName;
|
||||||
|
|
||||||
@JsonField(name = "lastPing")
|
/*@JsonField(name = "lastPing")
|
||||||
public long lastPing;
|
public long lastPing;*/
|
||||||
|
|
||||||
@JsonField(name = "sessionId")
|
@JsonField(name = "sessionId")
|
||||||
public String sessionId;
|
public String sessionId;
|
||||||
@ -56,7 +58,7 @@ public class Participant {
|
|||||||
@JsonField(name = "conversationId")
|
@JsonField(name = "conversationId")
|
||||||
public long conversationId;
|
public long conversationId;
|
||||||
|
|
||||||
@JsonField(name = { "inCall", "call" }, typeConverter = EnumParticipantFlagsConverter.class)
|
@JsonField(name = {"inCall", "call"}, typeConverter = EnumParticipantFlagsConverter.class)
|
||||||
public ParticipantFlags participantFlags;
|
public ParticipantFlags participantFlags;
|
||||||
|
|
||||||
@JsonField(name = "source")
|
@JsonField(name = "source")
|
||||||
@ -64,6 +66,27 @@ public class Participant {
|
|||||||
|
|
||||||
public boolean selected;
|
public boolean selected;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof Participant)) return false;
|
||||||
|
Participant that = (Participant) o;
|
||||||
|
return conversationId == that.conversationId &&
|
||||||
|
selected == that.selected &&
|
||||||
|
Objects.equals(userId, that.userId) &&
|
||||||
|
type == that.type &&
|
||||||
|
Objects.equals(name, that.name) &&
|
||||||
|
Objects.equals(displayName, that.displayName) &&
|
||||||
|
Objects.equals(sessionId, that.sessionId) &&
|
||||||
|
participantFlags == that.participantFlags &&
|
||||||
|
Objects.equals(source, that.source);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(userId, type, name, displayName, sessionId, conversationId, participantFlags, source, selected);
|
||||||
|
}
|
||||||
|
|
||||||
public enum ParticipantType {
|
public enum ParticipantType {
|
||||||
OWNER(1),
|
OWNER(1),
|
||||||
MODERATOR(2),
|
MODERATOR(2),
|
||||||
@ -72,13 +95,13 @@ public class Participant {
|
|||||||
USER_FOLLOWING_LINK(5),
|
USER_FOLLOWING_LINK(5),
|
||||||
GUEST_AS_MODERATOR(6);
|
GUEST_AS_MODERATOR(6);
|
||||||
|
|
||||||
private long value;
|
private Integer value;
|
||||||
|
|
||||||
ParticipantType(long value) {
|
ParticipantType(Integer value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ParticipantType fromValue(long value) {
|
public static ParticipantType fromValue(Integer value) {
|
||||||
if (value == 1) {
|
if (value == 1) {
|
||||||
return OWNER;
|
return OWNER;
|
||||||
} else if (value == 2) {
|
} else if (value == 2) {
|
||||||
@ -96,7 +119,7 @@ public class Participant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getValue() {
|
public Integer getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,13 +132,13 @@ public class Participant {
|
|||||||
IN_CALL_WITH_VIDEO(5),
|
IN_CALL_WITH_VIDEO(5),
|
||||||
IN_CALL_WITH_AUDIO_AND_VIDEO(7);
|
IN_CALL_WITH_AUDIO_AND_VIDEO(7);
|
||||||
|
|
||||||
private long value;
|
private Integer value;
|
||||||
|
|
||||||
ParticipantFlags(long value) {
|
ParticipantFlags(Integer value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ParticipantFlags fromValue(long value) {
|
public static ParticipantFlags fromValue(Integer value) {
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
return NOT_IN_CALL;
|
return NOT_IN_CALL;
|
||||||
} else if (value == 1) {
|
} else if (value == 1) {
|
||||||
@ -131,7 +154,7 @@ public class Participant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getValue() {
|
public Integer getValue() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import com.nextcloud.talk.newarch.domain.repository.offline.MessagesRepository
|
|||||||
import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkRepository
|
import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkRepository
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.*
|
import com.nextcloud.talk.newarch.domain.usecases.*
|
||||||
import com.nextcloud.talk.newarch.features.chat.ChatViewModelFactory
|
import com.nextcloud.talk.newarch.features.chat.ChatViewModelFactory
|
||||||
import com.nextcloud.talk.newarch.utils.GlobalService
|
import com.nextcloud.talk.newarch.services.GlobalService
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val ConversationsModule = module {
|
val ConversationsModule = module {
|
||||||
|
@ -5,7 +5,7 @@ import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsReposit
|
|||||||
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.GetConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.GetConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.JoinConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.JoinConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.utils.GlobalService
|
import com.nextcloud.talk.newarch.services.GlobalService
|
||||||
import com.nextcloud.talk.newarch.utils.ShortcutService
|
import com.nextcloud.talk.newarch.utils.ShortcutService
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
@ -11,8 +11,8 @@ import com.nextcloud.talk.newarch.domain.repository.offline.MessagesRepository
|
|||||||
import com.nextcloud.talk.newarch.domain.usecases.ExitConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.ExitConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.JoinConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.JoinConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
import com.nextcloud.talk.newarch.utils.GlobalService
|
import com.nextcloud.talk.newarch.services.GlobalService
|
||||||
import com.nextcloud.talk.newarch.utils.GlobalServiceInterface
|
import com.nextcloud.talk.newarch.services.GlobalServiceInterface
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class ChatViewModel constructor(application: Application,
|
class ChatViewModel constructor(application: Application,
|
||||||
|
@ -7,7 +7,7 @@ import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsReposit
|
|||||||
import com.nextcloud.talk.newarch.domain.repository.offline.MessagesRepository
|
import com.nextcloud.talk.newarch.domain.repository.offline.MessagesRepository
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.ExitConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.ExitConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.JoinConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.JoinConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.utils.GlobalService
|
import com.nextcloud.talk.newarch.services.GlobalService
|
||||||
|
|
||||||
class ChatViewModelFactory constructor(
|
class ChatViewModelFactory constructor(
|
||||||
private val application: Application,
|
private val application: Application,
|
||||||
|
@ -24,11 +24,11 @@ import android.app.Application
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
||||||
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.DeleteConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.DeleteConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.GetConversationsUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.GetConversationsUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.LeaveConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.LeaveConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.SetConversationFavoriteValueUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.SetConversationFavoriteValueUseCase
|
||||||
|
import com.nextcloud.talk.newarch.services.GlobalService
|
||||||
|
|
||||||
class ConversationListViewModelFactory constructor(
|
class ConversationListViewModelFactory constructor(
|
||||||
private val application: Application,
|
private val application: Application,
|
||||||
@ -37,14 +37,14 @@ class ConversationListViewModelFactory constructor(
|
|||||||
private val leaveConversationUseCase: LeaveConversationUseCase,
|
private val leaveConversationUseCase: LeaveConversationUseCase,
|
||||||
private val deleteConversationUseCase: DeleteConversationUseCase,
|
private val deleteConversationUseCase: DeleteConversationUseCase,
|
||||||
private val conversationsRepository: ConversationsRepository,
|
private val conversationsRepository: ConversationsRepository,
|
||||||
private val usersRepository: UsersRepository
|
private val globalService: GlobalService
|
||||||
) : ViewModelProvider.Factory {
|
) : ViewModelProvider.Factory {
|
||||||
|
|
||||||
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
||||||
return ConversationsListViewModel(
|
return ConversationsListViewModel(
|
||||||
application, conversationsUseCase,
|
application, conversationsUseCase,
|
||||||
setConversationFavoriteValueUseCase, leaveConversationUseCase, deleteConversationUseCase,
|
setConversationFavoriteValueUseCase, leaveConversationUseCase, deleteConversationUseCase,
|
||||||
conversationsRepository, usersRepository
|
conversationsRepository, globalService
|
||||||
) as T
|
) as T
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ package com.nextcloud.talk.newarch.features.conversationsList
|
|||||||
import android.app.SearchManager
|
import android.app.SearchManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
@ -32,13 +31,10 @@ import android.view.inputmethod.EditorInfo
|
|||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.appcompat.widget.SearchView.OnQueryTextListener
|
import androidx.appcompat.widget.SearchView.OnQueryTextListener
|
||||||
import androidx.core.view.MenuItemCompat
|
import androidx.core.view.MenuItemCompat
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||||
import butterknife.OnClick
|
import butterknife.OnClick
|
||||||
import coil.ImageLoader
|
|
||||||
import coil.target.Target
|
|
||||||
import coil.transform.CircleCropTransformation
|
|
||||||
import com.afollestad.materialdialogs.LayoutMode.WRAP_CONTENT
|
import com.afollestad.materialdialogs.LayoutMode.WRAP_CONTENT
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
||||||
@ -55,10 +51,8 @@ import com.nextcloud.talk.controllers.bottomsheet.items.BasicListItemWithImage
|
|||||||
import com.nextcloud.talk.controllers.bottomsheet.items.listItemsWithImage
|
import com.nextcloud.talk.controllers.bottomsheet.items.listItemsWithImage
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
import com.nextcloud.talk.newarch.conversationsList.mvp.BaseView
|
import com.nextcloud.talk.newarch.conversationsList.mvp.BaseView
|
||||||
import com.nextcloud.talk.newarch.features.conversationsList.ConversationsListViewState.*
|
import com.nextcloud.talk.newarch.features.conversationsList.ConversationsListViewNetworkState.*
|
||||||
import com.nextcloud.talk.newarch.mvvm.ext.initRecyclerView
|
import com.nextcloud.talk.newarch.mvvm.ext.initRecyclerView
|
||||||
import com.nextcloud.talk.newarch.utils.Images
|
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
|
||||||
import com.nextcloud.talk.utils.ConductorRemapping
|
import com.nextcloud.talk.utils.ConductorRemapping
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
import com.nextcloud.talk.utils.DisplayUtils
|
||||||
import com.nextcloud.talk.utils.ShareUtils
|
import com.nextcloud.talk.utils.ShareUtils
|
||||||
@ -81,8 +75,6 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
|||||||
|
|
||||||
private lateinit var viewModel: ConversationsListViewModel
|
private lateinit var viewModel: ConversationsListViewModel
|
||||||
val factory: ConversationListViewModelFactory by inject()
|
val factory: ConversationListViewModelFactory by inject()
|
||||||
private val imageLoader: ImageLoader by inject()
|
|
||||||
private val viewState: MutableLiveData<ConversationsListViewState> = MutableLiveData(LOADING)
|
|
||||||
|
|
||||||
private val recyclerViewAdapter = FlexibleAdapter(mutableListOf(), null, false)
|
private val recyclerViewAdapter = FlexibleAdapter(mutableListOf(), null, false)
|
||||||
|
|
||||||
@ -109,42 +101,7 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
|||||||
}
|
}
|
||||||
|
|
||||||
settingsItem = menu.findItem(R.id.action_settings)
|
settingsItem = menu.findItem(R.id.action_settings)
|
||||||
}
|
viewModel.loadAvatar()
|
||||||
|
|
||||||
private fun loadAvatar() {
|
|
||||||
val iconSize = settingsItem?.icon?.intrinsicHeight?.toFloat()
|
|
||||||
?.let {
|
|
||||||
DisplayUtils.convertDpToPixel(
|
|
||||||
it,
|
|
||||||
activity!!
|
|
||||||
)
|
|
||||||
.toInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
iconSize?.let {
|
|
||||||
val target = object : Target {
|
|
||||||
override fun onSuccess(result: Drawable) {
|
|
||||||
super.onSuccess(result)
|
|
||||||
settingsItem?.icon = result
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(error: Drawable?) {
|
|
||||||
super.onError(error)
|
|
||||||
settingsItem?.icon = context.getDrawable(R.drawable.ic_settings_white_24dp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
viewModel.currentUserLiveData.value?.let {
|
|
||||||
val avatarRequest = Images().getRequestForUrl(
|
|
||||||
imageLoader, context, ApiUtils.getUrlForAvatarWithNameAndPixels(
|
|
||||||
it.baseUrl,
|
|
||||||
it.userId, iconSize
|
|
||||||
), it, target, this, CircleCropTransformation()
|
|
||||||
)
|
|
||||||
|
|
||||||
imageLoader.load(avatarRequest)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
@ -186,10 +143,6 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
|||||||
searchView!!.setOnQueryTextListener(this)
|
searchView!!.setOnQueryTextListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRestoreViewState(view: View, savedViewState: Bundle) {
|
|
||||||
super.onRestoreViewState(view, savedViewState)
|
|
||||||
viewModel.loadConversations()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onQueryTextSubmit(query: String?): Boolean {
|
override fun onQueryTextSubmit(query: String?): Boolean {
|
||||||
if (!viewModel.searchQuery.value.equals(query)) {
|
if (!viewModel.searchQuery.value.equals(query)) {
|
||||||
@ -212,26 +165,32 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
|||||||
|
|
||||||
viewModel = viewModelProvider(factory).get(ConversationsListViewModel::class.java)
|
viewModel = viewModelProvider(factory).get(ConversationsListViewModel::class.java)
|
||||||
viewModel.apply {
|
viewModel.apply {
|
||||||
currentUserLiveData.observe(this@ConversationsListView, Observer { value ->
|
currentUserAvatar.observe(this@ConversationsListView, Observer { value ->
|
||||||
loadAvatar()
|
settingsItem?.icon = value
|
||||||
})
|
})
|
||||||
|
|
||||||
conversationsLiveData.observe(this@ConversationsListView, Observer {
|
conversationsLiveData.observe(this@ConversationsListView, Observer {
|
||||||
if (it.isEmpty()) {
|
val isListEmpty = it.isNullOrEmpty()
|
||||||
if (viewState.value != LOADED_EMPTY) {
|
|
||||||
viewState.value = LOADED_EMPTY
|
if (isListEmpty) {
|
||||||
}
|
view?.stateWithMessageView?.errorStateTextView?.text =
|
||||||
} else {
|
resources?.getText(R.string.nc_conversations_empty)
|
||||||
if (viewState.value != LOADED) {
|
view?.stateWithMessageView?.errorStateImageView?.setImageResource(drawable.ic_logo)
|
||||||
viewState.value = LOADED
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
view?.stateWithMessageView?.visibility = if (isListEmpty && networkStateLiveData.value != LOADING) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
|
if (view?.floatingActionButton?.isShown == false) {
|
||||||
|
view?.floatingActionButton?.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
searchItem?.isVisible = !isListEmpty
|
||||||
|
|
||||||
val newConversations = mutableListOf<ConversationItem>()
|
val newConversations = mutableListOf<ConversationItem>()
|
||||||
for (conversation in it) {
|
for (conversation in it) {
|
||||||
newConversations.add(
|
newConversations.add(
|
||||||
ConversationItem(
|
ConversationItem(
|
||||||
conversation, viewModel.currentUserLiveData.value!!,
|
conversation, globalService.currentUserLiveData.value!!,
|
||||||
activity!!
|
activity!!
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -241,6 +200,46 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
|||||||
newConversations as
|
newConversations as
|
||||||
List<IFlexible<ViewHolder>>?, false
|
List<IFlexible<ViewHolder>>?, false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
networkStateLiveData.observe(this@ConversationsListView, Observer { value ->
|
||||||
|
when (value) {
|
||||||
|
LOADING -> {
|
||||||
|
view?.post {
|
||||||
|
view?.loadingStateView?.visibility = View.VISIBLE
|
||||||
|
view?.dataStateView?.visibility = View.GONE
|
||||||
|
view?.stateWithMessageView?.visibility = View.GONE
|
||||||
|
view?.floatingActionButton?.visibility = View.GONE
|
||||||
|
}
|
||||||
|
searchItem?.isVisible = false
|
||||||
|
}
|
||||||
|
LOADED -> {
|
||||||
|
// awesome, but we delegate the magic stuff to the data handler
|
||||||
|
view?.post {
|
||||||
|
view?.loadingStateView?.visibility = View.GONE
|
||||||
|
view?.dataStateView?.visibility = View.VISIBLE
|
||||||
|
view?.floatingActionButton?.visibility = View.VISIBLE
|
||||||
|
if (view?.floatingActionButton?.isShown == false) {
|
||||||
|
view?.floatingActionButton?.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
searchItem?.isVisible = !recyclerViewAdapter.isEmpty
|
||||||
|
}
|
||||||
|
FAILED -> {
|
||||||
|
// probably offline, so what? :)
|
||||||
|
view?.post {
|
||||||
|
view?.loadingStateView?.visibility = View.GONE
|
||||||
|
view?.dataStateView?.visibility = View.VISIBLE
|
||||||
|
view?.floatingActionButton?.visibility = View.GONE
|
||||||
|
view?.stateWithMessageView?.visibility = if (recyclerViewAdapter.isEmpty) View.VISIBLE else View.GONE
|
||||||
|
}
|
||||||
|
searchItem?.isVisible = !recyclerViewAdapter.isEmpty
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
// We should not be here
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
searchQuery.observe(this@ConversationsListView, Observer {
|
searchQuery.observe(this@ConversationsListView, Observer {
|
||||||
@ -249,65 +248,6 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
viewState.observe(this@ConversationsListView, Observer { value ->
|
|
||||||
when (value) {
|
|
||||||
LOADING -> {
|
|
||||||
view?.swipeRefreshLayoutView?.isEnabled = false
|
|
||||||
view?.loadingStateView?.visibility = View.VISIBLE
|
|
||||||
view?.stateWithMessageView?.visibility = View.GONE
|
|
||||||
view?.dataStateView?.visibility = View.GONE
|
|
||||||
view?.floatingActionButton?.visibility = View.GONE
|
|
||||||
searchItem?.isVisible = false
|
|
||||||
}
|
|
||||||
LOADED -> {
|
|
||||||
view?.swipeRefreshLayoutView?.isEnabled = true
|
|
||||||
view?.swipeRefreshLayoutView?.post {
|
|
||||||
view?.swipeRefreshLayoutView?.isRefreshing = false
|
|
||||||
}
|
|
||||||
view?.loadingStateView?.visibility = View.GONE
|
|
||||||
view?.stateWithMessageView?.visibility = View.GONE
|
|
||||||
view?.dataStateView?.visibility = View.VISIBLE
|
|
||||||
view?.floatingActionButton?.visibility = View.VISIBLE
|
|
||||||
searchItem?.isVisible = true
|
|
||||||
}
|
|
||||||
LOADED_EMPTY, FAILED -> {
|
|
||||||
view?.swipeRefreshLayoutView?.post {
|
|
||||||
view?.swipeRefreshLayoutView?.isRefreshing = false
|
|
||||||
}
|
|
||||||
view?.swipeRefreshLayoutView?.isEnabled = true
|
|
||||||
view?.loadingStateView?.visibility = View.GONE
|
|
||||||
view?.dataStateView?.visibility = View.GONE
|
|
||||||
searchItem?.isVisible = false
|
|
||||||
|
|
||||||
if (value.equals(FAILED)) {
|
|
||||||
view?.stateWithMessageView?.errorStateTextView?.text = viewModel.messageData
|
|
||||||
if (viewModel.messageData.equals(
|
|
||||||
context.resources.getString(R.string.nc_no_connection_error)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
view?.stateWithMessageView?.errorStateImageView?.setImageResource(
|
|
||||||
drawable.ic_signal_wifi_off_white_24dp
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
view?.stateWithMessageView?.errorStateImageView?.setImageResource(
|
|
||||||
drawable.ic_announcement_white_24dp
|
|
||||||
)
|
|
||||||
}
|
|
||||||
view?.floatingActionButton?.visibility = View.GONE
|
|
||||||
} else {
|
|
||||||
view?.floatingActionButton?.visibility = View.VISIBLE
|
|
||||||
view?.stateWithMessageView?.errorStateTextView?.text =
|
|
||||||
resources?.getText(R.string.nc_conversations_empty)
|
|
||||||
view?.stateWithMessageView?.errorStateImageView?.setImageResource(drawable.ic_logo)
|
|
||||||
}
|
|
||||||
|
|
||||||
view?.stateWithMessageView?.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
// We should not be here
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
return super.onCreateView(inflater, container)
|
return super.onCreateView(inflater, container)
|
||||||
@ -324,7 +264,7 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
|||||||
|
|
||||||
@OnClick(R.id.stateWithMessageView)
|
@OnClick(R.id.stateWithMessageView)
|
||||||
fun onStateWithMessageViewClick() {
|
fun onStateWithMessageViewClick() {
|
||||||
if (viewState.value!! == LOADED_EMPTY) {
|
if (view?.floatingActionButton?.isVisible == true) {
|
||||||
openNewConversationScreen()
|
openNewConversationScreen()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,7 +332,7 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conversation.canLeave(viewModel.currentUserLiveData.value!!)) {
|
if (conversation.canLeave(viewModel.globalService.currentUserLiveData.value!!)) {
|
||||||
items.add(
|
items.add(
|
||||||
BasicListItemWithImage(
|
BasicListItemWithImage(
|
||||||
drawable.ic_exit_to_app_black_24dp, context.getString
|
drawable.ic_exit_to_app_black_24dp, context.getString
|
||||||
@ -401,7 +341,7 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conversation.canModerate(viewModel.currentUserLiveData.value!!)) {
|
if (conversation.canModerate(viewModel.globalService.currentUserLiveData.value!!)) {
|
||||||
items.add(
|
items.add(
|
||||||
BasicListItemWithImage(
|
BasicListItemWithImage(
|
||||||
drawable.ic_delete_grey600_24dp, context.getString(
|
drawable.ic_delete_grey600_24dp, context.getString(
|
||||||
@ -418,6 +358,11 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
|||||||
return resources?.getString(R.string.nc_app_name)
|
return resources?.getString(R.string.nc_app_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onRestoreViewState(view: View, savedViewState: Bundle) {
|
||||||
|
super.onRestoreViewState(view, savedViewState)
|
||||||
|
viewModel.loadConversations()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onAttach(view: View) {
|
override fun onAttach(view: View) {
|
||||||
super.onAttach(view)
|
super.onAttach(view)
|
||||||
view.recyclerView.initRecyclerView(
|
view.recyclerView.initRecyclerView(
|
||||||
@ -432,7 +377,6 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
|||||||
view.swipeRefreshLayoutView.isRefreshing = false
|
view.swipeRefreshLayoutView.isRefreshing = false
|
||||||
viewModel.loadConversations()
|
viewModel.loadConversations()
|
||||||
}
|
}
|
||||||
|
|
||||||
view.swipeRefreshLayoutView.setColorSchemeResources(R.color.colorPrimary)
|
view.swipeRefreshLayoutView.setColorSchemeResources(R.color.colorPrimary)
|
||||||
|
|
||||||
view.fast_scroller.setBubbleTextCreator { position ->
|
view.fast_scroller.setBubbleTextCreator { position ->
|
||||||
@ -514,15 +458,16 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
val clickedItem = recyclerViewAdapter.getItem(position)
|
val clickedItem = recyclerViewAdapter.getItem(position)
|
||||||
if (clickedItem != null) {
|
if (clickedItem != null) {
|
||||||
val conversation = (clickedItem as ConversationItem).model
|
val conversationItem = clickedItem as ConversationItem
|
||||||
|
val conversation = conversationItem.model
|
||||||
|
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, viewModel.currentUserLiveData.value)
|
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, conversationItem.user)
|
||||||
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, conversation.token)
|
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, conversation.token)
|
||||||
bundle.putString(BundleKeys.KEY_ROOM_ID, conversation.conversationId)
|
bundle.putString(BundleKeys.KEY_ROOM_ID, conversation.conversationId)
|
||||||
bundle.putParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION, Parcels.wrap(conversation))
|
bundle.putParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION, Parcels.wrap(conversation))
|
||||||
ConductorRemapping.remapChatController(
|
ConductorRemapping.remapChatController(
|
||||||
router, viewModel.currentUserLiveData.value!!.id!!, conversation.token!!,
|
router, conversationItem.user.id!!, conversation.token!!,
|
||||||
bundle, false
|
bundle, false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -21,30 +21,31 @@
|
|||||||
package com.nextcloud.talk.newarch.features.conversationsList
|
package com.nextcloud.talk.newarch.features.conversationsList
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Intent
|
import android.graphics.drawable.Drawable
|
||||||
import androidx.lifecycle.LiveData
|
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.Transformations
|
import androidx.lifecycle.Transformations
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import coil.Coil
|
||||||
|
import coil.api.get
|
||||||
|
import coil.transform.CircleCropTransformation
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.R.drawable
|
|
||||||
import com.nextcloud.talk.R.string
|
|
||||||
import com.nextcloud.talk.controllers.bottomsheet.items.BasicListItemWithImage
|
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||||
import com.nextcloud.talk.newarch.conversationsList.mvp.BaseViewModel
|
import com.nextcloud.talk.newarch.conversationsList.mvp.BaseViewModel
|
||||||
import com.nextcloud.talk.newarch.data.model.ErrorModel
|
import com.nextcloud.talk.newarch.data.model.ErrorModel
|
||||||
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
||||||
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.DeleteConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.DeleteConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.GetConversationsUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.GetConversationsUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.LeaveConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.LeaveConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.SetConversationFavoriteValueUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.SetConversationFavoriteValueUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse
|
import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse
|
||||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
import com.nextcloud.talk.newarch.local.models.getCredentials
|
||||||
import com.nextcloud.talk.utils.ShareUtils
|
import com.nextcloud.talk.newarch.services.GlobalService
|
||||||
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
|
import com.nextcloud.talk.utils.DisplayUtils
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.core.parameter.parametersOf
|
import org.koin.core.parameter.parametersOf
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
|
||||||
class ConversationsListViewModel constructor(
|
class ConversationsListViewModel constructor(
|
||||||
application: Application,
|
application: Application,
|
||||||
@ -53,14 +54,21 @@ class ConversationsListViewModel constructor(
|
|||||||
private val leaveConversationUseCase: LeaveConversationUseCase,
|
private val leaveConversationUseCase: LeaveConversationUseCase,
|
||||||
private val deleteConversationUseCase: DeleteConversationUseCase,
|
private val deleteConversationUseCase: DeleteConversationUseCase,
|
||||||
private val conversationsRepository: ConversationsRepository,
|
private val conversationsRepository: ConversationsRepository,
|
||||||
usersRepository: UsersRepository
|
val globalService: GlobalService
|
||||||
) : BaseViewModel<ConversationsListView>(application) {
|
) : BaseViewModel<ConversationsListView>(application) {
|
||||||
|
|
||||||
|
private val conversationsLoadingLock = ReentrantLock()
|
||||||
|
|
||||||
var messageData: String? = null
|
var messageData: String? = null
|
||||||
val searchQuery = MutableLiveData<String>()
|
val searchQuery = MutableLiveData<String>()
|
||||||
val currentUserLiveData: LiveData<UserNgEntity> = usersRepository.getActiveUserLiveData()
|
val networkStateLiveData: MutableLiveData<ConversationsListViewNetworkState> = MutableLiveData(ConversationsListViewNetworkState.LOADING)
|
||||||
val conversationsLiveData = Transformations.switchMap(currentUserLiveData) {
|
val currentUserAvatar: MutableLiveData<Drawable> = MutableLiveData(DisplayUtils.getRoundedDrawable(context.getDrawable(R.drawable.ic_settings_white_24dp)))
|
||||||
|
val conversationsLiveData = Transformations.switchMap(globalService.currentUserLiveData) {
|
||||||
|
if (networkStateLiveData.value != ConversationsListViewNetworkState.LOADING) {
|
||||||
|
networkStateLiveData.postValue(ConversationsListViewNetworkState.LOADING)
|
||||||
|
}
|
||||||
loadConversations()
|
loadConversations()
|
||||||
|
loadAvatar()
|
||||||
conversationsRepository.getConversationsForUser(it.id!!)
|
conversationsRepository.getConversationsForUser(it.id!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,13 +78,13 @@ class ConversationsListViewModel constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
leaveConversationUseCase.invoke(viewModelScope, parametersOf(
|
leaveConversationUseCase.invoke(viewModelScope, parametersOf(
|
||||||
currentUserLiveData.value,
|
globalService.currentUserLiveData.value,
|
||||||
conversation
|
conversation
|
||||||
),
|
),
|
||||||
object : UseCaseResponse<GenericOverall> {
|
object : UseCaseResponse<GenericOverall> {
|
||||||
override suspend fun onSuccess(result: GenericOverall) {
|
override suspend fun onSuccess(result: GenericOverall) {
|
||||||
conversationsRepository.deleteConversation(
|
conversationsRepository.deleteConversation(
|
||||||
currentUserLiveData.value!!.id!!, conversation
|
globalService.currentUserLiveData.value!!.id!!, conversation
|
||||||
.conversationId!!
|
.conversationId!!
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -99,13 +107,13 @@ class ConversationsListViewModel constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
deleteConversationUseCase.invoke(viewModelScope, parametersOf(
|
deleteConversationUseCase.invoke(viewModelScope, parametersOf(
|
||||||
currentUserLiveData.value,
|
globalService.currentUserLiveData.value,
|
||||||
conversation
|
conversation
|
||||||
),
|
),
|
||||||
object : UseCaseResponse<GenericOverall> {
|
object : UseCaseResponse<GenericOverall> {
|
||||||
override suspend fun onSuccess(result: GenericOverall) {
|
override suspend fun onSuccess(result: GenericOverall) {
|
||||||
conversationsRepository.deleteConversation(
|
conversationsRepository.deleteConversation(
|
||||||
currentUserLiveData.value!!.id!!, conversation
|
globalService.currentUserLiveData.value!!.id!!, conversation
|
||||||
.conversationId!!
|
.conversationId!!
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -129,14 +137,14 @@ class ConversationsListViewModel constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
setConversationFavoriteValueUseCase.invoke(viewModelScope, parametersOf(
|
setConversationFavoriteValueUseCase.invoke(viewModelScope, parametersOf(
|
||||||
currentUserLiveData.value,
|
globalService.currentUserLiveData.value,
|
||||||
conversation,
|
conversation,
|
||||||
favorite
|
favorite
|
||||||
),
|
),
|
||||||
object : UseCaseResponse<GenericOverall> {
|
object : UseCaseResponse<GenericOverall> {
|
||||||
override suspend fun onSuccess(result: GenericOverall) {
|
override suspend fun onSuccess(result: GenericOverall) {
|
||||||
conversationsRepository.setFavoriteValueForConversation(
|
conversationsRepository.setFavoriteValueForConversation(
|
||||||
currentUserLiveData.value!!.id!!,
|
globalService.currentUserLiveData.value!!.id!!,
|
||||||
conversation.conversationId!!, favorite
|
conversation.conversationId!!, favorite
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -150,12 +158,30 @@ class ConversationsListViewModel constructor(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun loadAvatar() {
|
||||||
|
val operationUser = globalService.currentUserLiveData.value
|
||||||
|
|
||||||
|
operationUser?.let {
|
||||||
|
viewModelScope.launch {
|
||||||
|
val url = ApiUtils.getUrlForAvatarWithNameAndPixels(it.baseUrl, it.userId, 512)
|
||||||
|
val drawable = Coil.get((url)) {
|
||||||
|
addHeader("Authorization", it.getCredentials())
|
||||||
|
transformations(CircleCropTransformation())
|
||||||
|
}
|
||||||
|
currentUserAvatar.postValue(drawable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun loadConversations() {
|
fun loadConversations() {
|
||||||
getConversationsUseCase.invoke(viewModelScope, parametersOf(currentUserLiveData.value), object :
|
if (conversationsLoadingLock.tryLock()) {
|
||||||
|
getConversationsUseCase.invoke(viewModelScope, parametersOf(globalService.currentUserLiveData.value), object :
|
||||||
UseCaseResponse<List<Conversation>> {
|
UseCaseResponse<List<Conversation>> {
|
||||||
override suspend fun onSuccess(result: List<Conversation>) {
|
override suspend fun onSuccess(
|
||||||
|
result: List<Conversation>) {
|
||||||
|
networkStateLiveData.postValue(ConversationsListViewNetworkState.LOADED)
|
||||||
val mutableList = result.toMutableList()
|
val mutableList = result.toMutableList()
|
||||||
val internalUserId = currentUserLiveData.value!!.id
|
val internalUserId = globalService.currentUserLiveData.value!!.id
|
||||||
mutableList.forEach {
|
mutableList.forEach {
|
||||||
it.internalUserId = internalUserId
|
it.internalUserId = internalUserId
|
||||||
}
|
}
|
||||||
@ -164,13 +190,17 @@ class ConversationsListViewModel constructor(
|
|||||||
internalUserId!!,
|
internalUserId!!,
|
||||||
mutableList)
|
mutableList)
|
||||||
messageData = ""
|
messageData = ""
|
||||||
|
conversationsLoadingLock.unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun onError(errorModel: ErrorModel?) {
|
override suspend fun onError(errorModel: ErrorModel?) {
|
||||||
messageData = errorModel?.getErrorMessage()
|
messageData = errorModel?.getErrorMessage()
|
||||||
|
networkStateLiveData.postValue(ConversationsListViewNetworkState.FAILED)
|
||||||
|
conversationsLoadingLock.unlock()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private suspend fun setConversationUpdateStatus(
|
private suspend fun setConversationUpdateStatus(
|
||||||
@ -178,7 +208,7 @@ class ConversationsListViewModel constructor(
|
|||||||
value: Boolean
|
value: Boolean
|
||||||
) {
|
) {
|
||||||
conversationsRepository.setChangingValueForConversation(
|
conversationsRepository.setChangingValueForConversation(
|
||||||
currentUserLiveData.value!!.id!!, conversation
|
globalService.currentUserLiveData.value!!.id!!, conversation
|
||||||
.conversationId!!, value
|
.conversationId!!, value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,7 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.newarch.features.conversationsList
|
package com.nextcloud.talk.newarch.features.conversationsList
|
||||||
|
|
||||||
enum class ConversationsListViewState {
|
enum class ConversationsListViewNetworkState {
|
||||||
INITIAL_LOAD,
|
|
||||||
LOADING,
|
LOADING,
|
||||||
LOADED_EMPTY,
|
LOADED_EMPTY,
|
||||||
LOADED,
|
LOADED,
|
@ -22,12 +22,12 @@ package com.nextcloud.talk.newarch.features.conversationsList.di.module
|
|||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
||||||
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.DeleteConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.DeleteConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.GetConversationsUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.GetConversationsUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.LeaveConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.LeaveConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.SetConversationFavoriteValueUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.SetConversationFavoriteValueUseCase
|
||||||
import com.nextcloud.talk.newarch.features.conversationsList.ConversationListViewModelFactory
|
import com.nextcloud.talk.newarch.features.conversationsList.ConversationListViewModelFactory
|
||||||
|
import com.nextcloud.talk.newarch.services.GlobalService
|
||||||
import org.koin.android.ext.koin.androidApplication
|
import org.koin.android.ext.koin.androidApplication
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
@ -49,11 +49,11 @@ fun createConversationListViewModelFactory(
|
|||||||
leaveConversationUseCase: LeaveConversationUseCase,
|
leaveConversationUseCase: LeaveConversationUseCase,
|
||||||
deleteConversationUseCase: DeleteConversationUseCase,
|
deleteConversationUseCase: DeleteConversationUseCase,
|
||||||
conversationsRepository: ConversationsRepository,
|
conversationsRepository: ConversationsRepository,
|
||||||
usersRepository: UsersRepository
|
globalService: GlobalService
|
||||||
): ConversationListViewModelFactory {
|
): ConversationListViewModelFactory {
|
||||||
return ConversationListViewModelFactory(
|
return ConversationListViewModelFactory(
|
||||||
application, getConversationsUseCase,
|
application, getConversationsUseCase,
|
||||||
setConversationFavoriteValueUseCase, leaveConversationUseCase, deleteConversationUseCase,
|
setConversationFavoriteValueUseCase, leaveConversationUseCase, deleteConversationUseCase,
|
||||||
conversationsRepository, usersRepository
|
conversationsRepository, globalService
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -34,9 +34,9 @@ class ConversationReadOnlyStateConverter {
|
|||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun fromIntToConversationType(value: Int): ConversationReadOnlyState {
|
fun fromIntToConversationType(value: Int): ConversationReadOnlyState {
|
||||||
when (value) {
|
return when (value) {
|
||||||
0 -> return CONVERSATION_READ_WRITE
|
0 -> CONVERSATION_READ_WRITE
|
||||||
else -> return CONVERSATION_READ_ONLY
|
else -> CONVERSATION_READ_ONLY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,11 +26,11 @@ import com.nextcloud.talk.models.json.participants.Participant.ParticipantType
|
|||||||
class ParticipantTypeConverter {
|
class ParticipantTypeConverter {
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun fromParticipantType(participantType: ParticipantType): Int {
|
fun fromParticipantType(participantType: ParticipantType): Int {
|
||||||
return participantType.ordinal
|
return participantType.value
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
fun fromIntToParticipantType(value: Int): ParticipantType {
|
fun fromIntToParticipantType(value: Int): ParticipantType {
|
||||||
return ParticipantType.fromValue(value.toLong())
|
return ParticipantType.fromValue(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -96,7 +96,7 @@ data class ConversationEntity(
|
|||||||
if (lastActivity != other.lastActivity) return false
|
if (lastActivity != other.lastActivity) return false
|
||||||
if (unreadMessages != other.unreadMessages) return false
|
if (unreadMessages != other.unreadMessages) return false
|
||||||
if (unreadMention != other.unreadMention) return false
|
if (unreadMention != other.unreadMention) return false
|
||||||
if (lastMessage?.internalMessageId != other.lastMessage?.internalMessageId) return false
|
if (lastMessage != other.lastMessage) return false
|
||||||
if (objectType != other.objectType) return false
|
if (objectType != other.objectType) return false
|
||||||
if (notificationLevel != other.notificationLevel) return false
|
if (notificationLevel != other.notificationLevel) return false
|
||||||
if (conversationReadOnlyState != other.conversationReadOnlyState) return false
|
if (conversationReadOnlyState != other.conversationReadOnlyState) return false
|
||||||
|
@ -30,6 +30,7 @@ import com.nextcloud.talk.models.json.push.PushConfigurationState
|
|||||||
import com.nextcloud.talk.newarch.local.models.other.UserStatus
|
import com.nextcloud.talk.newarch.local.models.other.UserStatus
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
@Entity(tableName = "users")
|
@Entity(tableName = "users")
|
||||||
@ -63,7 +64,7 @@ data class UserNgEntity(
|
|||||||
other as UserNgEntity
|
other as UserNgEntity
|
||||||
|
|
||||||
if (userId != other.userId) return false
|
if (userId != other.userId) return false
|
||||||
if (username != other.username) return false
|
//if (username != other.username) return false
|
||||||
if (baseUrl != other.baseUrl) return false
|
if (baseUrl != other.baseUrl) return false
|
||||||
if (token != other.token) return false
|
if (token != other.token) return false
|
||||||
if (displayName != other.displayName) return false
|
if (displayName != other.displayName) return false
|
||||||
@ -77,7 +78,7 @@ data class UserNgEntity(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
return userId.hashCode()
|
return Objects.hash(userId, username)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,24 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
* Nextcloud Talk application
|
|
||||||
*
|
*
|
||||||
* @author Mario Danic
|
* * Nextcloud Talk application
|
||||||
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
* *
|
||||||
|
* * @author Mario Danic
|
||||||
|
* * Copyright (C) 2017-2020 Mario Danic <mario@lovelyhq.com>
|
||||||
|
* *
|
||||||
|
* * This program is free software: you can redistribute it and/or modify
|
||||||
|
* * it under the terms of the GNU General Public License as published by
|
||||||
|
* * the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* * at your option) any later version.
|
||||||
|
* *
|
||||||
|
* * This program is distributed in the hope that it will be useful,
|
||||||
|
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* * GNU General Public License for more details.
|
||||||
|
* *
|
||||||
|
* * You should have received a copy of the GNU General Public License
|
||||||
|
* * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.nextcloud.talk.newarch.utils
|
package com.nextcloud.talk.newarch.services
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* * Nextcloud Talk application
|
||||||
|
* *
|
||||||
|
* * @author Mario Danic
|
||||||
|
* * Copyright (C) 2017-2020 Mario Danic <mario@lovelyhq.com>
|
||||||
|
* *
|
||||||
|
* * This program is free software: you can redistribute it and/or modify
|
||||||
|
* * it under the terms of the GNU General Public License as published by
|
||||||
|
* * the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* * at your option) any later version.
|
||||||
|
* *
|
||||||
|
* * This program is distributed in the hope that it will be useful,
|
||||||
|
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* * GNU General Public License for more details.
|
||||||
|
* *
|
||||||
|
* * You should have received a copy of the GNU General Public License
|
||||||
|
* * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.talk.newarch.services
|
||||||
|
|
||||||
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
|
|
||||||
|
interface GlobalServiceInterface {
|
||||||
|
enum class OperationStatus {
|
||||||
|
STATUS_OK,
|
||||||
|
STATUS_FAILED
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun gotConversationInfoForUser(userNgEntity: UserNgEntity, conversation: Conversation?, operationStatus: OperationStatus)
|
||||||
|
suspend fun joinedConversationForUser(userNgEntity: UserNgEntity, conversation: Conversation?, operationStatus: OperationStatus)
|
||||||
|
}
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Talk application
|
|
||||||
*
|
|
||||||
* @author Mario Danic
|
|
||||||
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.nextcloud.talk.newarch.utils
|
|
||||||
|
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
|
||||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
|
||||||
|
|
||||||
interface GlobalServiceInterface {
|
|
||||||
enum class OperationStatus {
|
|
||||||
STATUS_OK,
|
|
||||||
STATUS_FAILED
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun gotConversationInfoForUser(userNgEntity: UserNgEntity, conversation: Conversation?, operationStatus: OperationStatus)
|
|
||||||
suspend fun joinedConversationForUser(userNgEntity: UserNgEntity, conversation: Conversation?, operationStatus: OperationStatus)
|
|
||||||
}
|
|
@ -20,18 +20,9 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.newarch.utils
|
package com.nextcloud.talk.newarch.utils
|
||||||
|
|
||||||
import android.app.ActivityManager
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Context.ACTIVITY_SERVICE
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.Rect
|
|
||||||
import android.graphics.drawable.BitmapDrawable
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.graphics.drawable.LayerDrawable
|
import android.graphics.drawable.LayerDrawable
|
||||||
import android.os.Build
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.core.content.ContextCompat.getSystemService
|
|
||||||
import androidx.core.graphics.drawable.toBitmap
|
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import coil.request.LoadRequest
|
import coil.request.LoadRequest
|
||||||
|
@ -42,6 +42,7 @@ import com.nextcloud.talk.models.json.conversations.Conversation
|
|||||||
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
|
||||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
import com.nextcloud.talk.newarch.local.models.getCredentials
|
import com.nextcloud.talk.newarch.local.models.getCredentials
|
||||||
|
import com.nextcloud.talk.newarch.services.GlobalService
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
@ -25,7 +25,9 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.graphics.*
|
import android.graphics.Bitmap
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Typeface
|
||||||
import android.graphics.drawable.BitmapDrawable
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
@ -47,7 +49,6 @@ import androidx.annotation.DrawableRes
|
|||||||
import androidx.annotation.XmlRes
|
import androidx.annotation.XmlRes
|
||||||
import androidx.appcompat.widget.AppCompatDrawableManager
|
import androidx.appcompat.widget.AppCompatDrawableManager
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.graphics.applyCanvas
|
|
||||||
import androidx.core.graphics.drawable.DrawableCompat
|
import androidx.core.graphics.drawable.DrawableCompat
|
||||||
import androidx.emoji.text.EmojiCompat
|
import androidx.emoji.text.EmojiCompat
|
||||||
import coil.Coil
|
import coil.Coil
|
||||||
@ -66,7 +67,6 @@ import kotlinx.coroutines.runBlocking
|
|||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import java.lang.reflect.InvocationTargetException
|
import java.lang.reflect.InvocationTargetException
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
object DisplayUtils {
|
object DisplayUtils {
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
android:id="@+id/stateWithMessageView"
|
android:id="@+id/stateWithMessageView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="gone"
|
||||||
>
|
>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
<!--
|
|
||||||
~ Nextcloud Talk application
|
~ Nextcloud Talk application
|
||||||
~
|
~
|
||||||
~ @author Mario Danic
|
~ @author Mario Danic
|
||||||
@ -23,18 +22,20 @@
|
|||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
<!-- Search, should appear as action button -->
|
<!-- Search, should appear as action button -->
|
||||||
<item android:id="@+id/action_search"
|
<item
|
||||||
android:title="@string/nc_search"
|
android:id="@+id/action_search"
|
||||||
android:icon="@drawable/ic_search_white_24dp"
|
|
||||||
app:showAsAction="collapseActionView|always"
|
|
||||||
android:animateLayoutChanges="true"
|
android:animateLayoutChanges="true"
|
||||||
|
android:icon="@drawable/ic_search_white_24dp"
|
||||||
|
android:title="@string/nc_search"
|
||||||
|
android:visible="false"
|
||||||
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||||
/>
|
app:showAsAction="collapseActionView|always" />
|
||||||
|
|
||||||
<item android:id="@+id/action_settings"
|
<item
|
||||||
android:title="@string/nc_settings"
|
android:id="@+id/action_settings"
|
||||||
android:icon="@drawable/ic_settings_white_24dp"
|
android:icon="@drawable/ic_settings_white_24dp"
|
||||||
app:showAsAction="ifRoom"/>
|
android:title="@string/nc_settings"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
|
Loading…
Reference in New Issue
Block a user