mirror of
https://github.com/nextcloud/talk-android
synced 2025-06-20 12:09:45 +01:00
More progress
Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
parent
b0c821462d
commit
2681e6ef24
@ -70,15 +70,18 @@ android {
|
||||
|
||||
javaCompileOptions {
|
||||
annotationProcessorOptions {
|
||||
arguments = [
|
||||
parcelerStacktrace: "true"
|
||||
]
|
||||
arguments = ["room.schemaLocation":
|
||||
"$projectDir/schemas".toString()]
|
||||
}
|
||||
}
|
||||
|
||||
dataBinding {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
androidExtensions {
|
||||
experimental = true
|
||||
}
|
||||
}
|
||||
|
||||
dexOptions {
|
||||
@ -109,6 +112,10 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
htmlReport true
|
||||
|
@ -0,0 +1,179 @@
|
||||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 1,
|
||||
"identityHash": "a547a767687b46e3e5768a3d77d5d212",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "conversations",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`user` INTEGER NOT NULL, `conversation_id` TEXT NOT NULL, `token` TEXT, `name` TEXT, `display_name` TEXT, `type` INTEGER, `count` INTEGER NOT NULL, `number_of_guests` INTEGER NOT NULL, `participants_count` INTEGER NOT NULL, `participant_type` INTEGER, `has_password` INTEGER NOT NULL, `session_id` TEXT, `favorite` INTEGER NOT NULL, `last_activity` INTEGER NOT NULL, `unread_messages` INTEGER NOT NULL, `unread_mention` INTEGER NOT NULL, `last_message` TEXT, `object_type` TEXT, `notification_level` INTEGER, `read_only_state` INTEGER, `lobby_state` INTEGER, `lobby_timer` INTEGER, `last_read_message_id` INTEGER NOT NULL, `modified_at` INTEGER, `changing` INTEGER NOT NULL, PRIMARY KEY(`user`, `conversation_id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "userId",
|
||||
"columnName": "user",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "conversationId",
|
||||
"columnName": "conversation_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "token",
|
||||
"columnName": "token",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "displayName",
|
||||
"columnName": "display_name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "count",
|
||||
"columnName": "count",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "numberOfGuests",
|
||||
"columnName": "number_of_guests",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "participantsCount",
|
||||
"columnName": "participants_count",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "participantType",
|
||||
"columnName": "participant_type",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "hasPassword",
|
||||
"columnName": "has_password",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "sessionId",
|
||||
"columnName": "session_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "favorite",
|
||||
"columnName": "favorite",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastActivity",
|
||||
"columnName": "last_activity",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "unreadMessages",
|
||||
"columnName": "unread_messages",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "unreadMention",
|
||||
"columnName": "unread_mention",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastMessage",
|
||||
"columnName": "last_message",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "objectType",
|
||||
"columnName": "object_type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "notificationLevel",
|
||||
"columnName": "notification_level",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "conversationReadOnlyState",
|
||||
"columnName": "read_only_state",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "lobbyState",
|
||||
"columnName": "lobby_state",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "lobbyTimer",
|
||||
"columnName": "lobby_timer",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastReadMessageId",
|
||||
"columnName": "last_read_message_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "modifiedAt",
|
||||
"columnName": "modified_at",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "changing",
|
||||
"columnName": "changing",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"user",
|
||||
"conversation_id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'a547a767687b46e3e5768a3d77d5d212')"
|
||||
]
|
||||
}
|
||||
}
|
@ -1,192 +0,0 @@
|
||||
/*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017 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.adapters.items;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import androidx.emoji.widget.EmojiTextView;
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.drawee.interfaces.DraweeController;
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
import com.nextcloud.talk.events.MoreMenuClickEvent;
|
||||
import com.nextcloud.talk.models.database.UserEntity;
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation;
|
||||
import com.nextcloud.talk.utils.ApiUtils;
|
||||
import com.nextcloud.talk.utils.DisplayUtils;
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
|
||||
import eu.davidea.flexibleadapter.items.IFilterable;
|
||||
import eu.davidea.flexibleadapter.utils.FlexibleUtils;
|
||||
import eu.davidea.viewholders.FlexibleViewHolder;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
public class CallItem extends AbstractFlexibleItem<CallItem.RoomItemViewHolder>
|
||||
implements IFilterable<String> {
|
||||
|
||||
private Conversation conversation;
|
||||
private UserEntity userEntity;
|
||||
|
||||
public CallItem(Conversation conversation, UserEntity userEntity) {
|
||||
this.conversation = conversation;
|
||||
this.userEntity = userEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof CallItem) {
|
||||
CallItem inItem = (CallItem) o;
|
||||
return conversation.equals(inItem.getModel());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return conversation.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the model object
|
||||
*/
|
||||
|
||||
public Conversation getModel() {
|
||||
return conversation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter is applied to the model fields.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public int getLayoutRes() {
|
||||
return R.layout.rv_item_conversation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RoomItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) {
|
||||
return new RoomItemViewHolder(view, adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindViewHolder(final FlexibleAdapter adapter, RoomItemViewHolder holder, int position,
|
||||
List payloads) {
|
||||
if (adapter.hasFilter()) {
|
||||
FlexibleUtils.highlightText(holder.roomDisplayName, conversation.getDisplayName(),
|
||||
String.valueOf(adapter.getFilter(String.class)),
|
||||
NextcloudTalkApplication.Companion.getSharedApplication()
|
||||
.getResources().getColor(R.color.colorPrimary));
|
||||
} else {
|
||||
holder.roomDisplayName.setText(conversation.getDisplayName());
|
||||
}
|
||||
|
||||
if (conversation.getLastPing() == 0) {
|
||||
holder.roomLastPing.setText(R.string.nc_never);
|
||||
} else {
|
||||
holder.roomLastPing.setText(
|
||||
DateUtils.getRelativeTimeSpanString(conversation.getLastPing() * 1000L,
|
||||
System.currentTimeMillis(), 0, DateUtils.FORMAT_ABBREV_RELATIVE));
|
||||
}
|
||||
|
||||
if (conversation.hasPassword) {
|
||||
holder.passwordProtectedImageView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.passwordProtectedImageView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
|
||||
switch (conversation.getType()) {
|
||||
case ROOM_TYPE_ONE_TO_ONE_CALL:
|
||||
holder.avatarImageView.setVisibility(View.VISIBLE);
|
||||
|
||||
holder.moreMenuButton.setContentDescription(String.format(resources.getString(R.string
|
||||
.nc_description_more_menu_one_to_one), conversation.getDisplayName()));
|
||||
|
||||
if (!TextUtils.isEmpty(conversation.getName())) {
|
||||
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
|
||||
.setOldController(holder.avatarImageView.getController())
|
||||
.setAutoPlayAnimations(true)
|
||||
.setImageRequest(DisplayUtils.getImageRequestForUrl(
|
||||
ApiUtils.getUrlForAvatarWithName(userEntity.getBaseUrl(),
|
||||
conversation.getName(),
|
||||
R.dimen.avatar_size), null))
|
||||
.build();
|
||||
holder.avatarImageView.setController(draweeController);
|
||||
} else {
|
||||
holder.avatarImageView.setVisibility(View.GONE);
|
||||
}
|
||||
break;
|
||||
case ROOM_GROUP_CALL:
|
||||
holder.moreMenuButton.setContentDescription(String.format(resources.getString(R.string
|
||||
.nc_description_more_menu_group), conversation.getDisplayName()));
|
||||
holder.avatarImageView.setActualImageResource(R.drawable.ic_people_group_white_24px);
|
||||
holder.avatarImageView.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case ROOM_PUBLIC_CALL:
|
||||
holder.moreMenuButton.setContentDescription(String.format(resources.getString(R.string
|
||||
.nc_description_more_menu_public), conversation.getDisplayName()));
|
||||
holder.avatarImageView.setActualImageResource(R.drawable.ic_link_white_24px);
|
||||
holder.avatarImageView.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
default:
|
||||
holder.avatarImageView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
holder.moreMenuButton.setOnClickListener(
|
||||
view -> EventBus.getDefault().post(new MoreMenuClickEvent(conversation)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean filter(String constraint) {
|
||||
return conversation.getDisplayName() != null &&
|
||||
Pattern.compile(constraint, Pattern.CASE_INSENSITIVE | Pattern.LITERAL)
|
||||
.matcher(conversation.getDisplayName().trim())
|
||||
.find();
|
||||
}
|
||||
|
||||
static class RoomItemViewHolder extends FlexibleViewHolder {
|
||||
|
||||
@BindView(R.id.name_text)
|
||||
public EmojiTextView roomDisplayName;
|
||||
@BindView(R.id.secondary_text)
|
||||
public EmojiTextView roomLastPing;
|
||||
@BindView(R.id.avatar_image)
|
||||
public SimpleDraweeView avatarImageView;
|
||||
@BindView(R.id.more_menu)
|
||||
public ImageButton moreMenuButton;
|
||||
@BindView(R.id.password_protected_image_view)
|
||||
ImageView passwordProtectedImageView;
|
||||
|
||||
RoomItemViewHolder(View view, FlexibleAdapter adapter) {
|
||||
super(view, adapter);
|
||||
ButterKnife.bind(this, view);
|
||||
}
|
||||
}
|
||||
}
|
@ -104,7 +104,7 @@ public class ConversationItem
|
||||
|
||||
holder.dialogAvatar.setController(null);
|
||||
|
||||
if (conversation.isUpdating()) {
|
||||
if (conversation.getChanging()) {
|
||||
holder.progressBar.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.progressBar.setVisibility(View.GONE);
|
||||
@ -127,7 +127,7 @@ public class ConversationItem
|
||||
holder.dialogUnreadBubble.setText("99+");
|
||||
}
|
||||
|
||||
if (conversation.isUnreadMention()) {
|
||||
if (conversation.getUnreadMention()) {
|
||||
holder.dialogUnreadBubble.setBackground(
|
||||
context.getDrawable(R.drawable.bubble_circle_unread_mention));
|
||||
} else {
|
||||
@ -138,13 +138,13 @@ public class ConversationItem
|
||||
holder.dialogUnreadBubble.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (conversation.isHasPassword()) {
|
||||
if (conversation.getHasPassword()) {
|
||||
holder.passwordProtectedRoomImageView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.passwordProtectedRoomImageView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (conversation.isFavorite()) {
|
||||
if (conversation.getFavorite()) {
|
||||
holder.pinnedConversationImageView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.pinnedConversationImageView.setVisibility(View.GONE);
|
||||
@ -157,7 +157,7 @@ public class ConversationItem
|
||||
System.currentTimeMillis(), 0, DateUtils.FORMAT_ABBREV_RELATIVE));
|
||||
|
||||
if (!TextUtils.isEmpty(conversation.getLastMessage().getSystemMessage())
|
||||
|| Conversation.ConversationType.ROOM_SYSTEM.equals(conversation.getType())) {
|
||||
|| Conversation.ConversationType.SYSTEM_CONVERSATION.equals(conversation.getType())) {
|
||||
holder.dialogLastMessage.setText(conversation.getLastMessage().getText());
|
||||
} else {
|
||||
String authorDisplayName = "";
|
||||
@ -213,7 +213,7 @@ public class ConversationItem
|
||||
}
|
||||
}
|
||||
|
||||
if (Conversation.ConversationType.ROOM_SYSTEM.equals(conversation.getType())) {
|
||||
if (Conversation.ConversationType.SYSTEM_CONVERSATION.equals(conversation.getType())) {
|
||||
Drawable[] layers = new Drawable[2];
|
||||
layers[0] = context.getDrawable(R.drawable.ic_launcher_background);
|
||||
layers[1] = context.getDrawable(R.drawable.ic_launcher_foreground);
|
||||
@ -227,7 +227,7 @@ public class ConversationItem
|
||||
|
||||
if (shouldLoadAvatar) {
|
||||
switch (conversation.getType()) {
|
||||
case ROOM_TYPE_ONE_TO_ONE_CALL:
|
||||
case ONE_TO_ONE_CONVERSATION:
|
||||
if (!TextUtils.isEmpty(conversation.getName())) {
|
||||
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
|
||||
.setOldController(holder.dialogAvatar.getController())
|
||||
@ -241,13 +241,13 @@ public class ConversationItem
|
||||
holder.dialogAvatar.setVisibility(View.GONE);
|
||||
}
|
||||
break;
|
||||
case ROOM_GROUP_CALL:
|
||||
case GROUP_CONVERSATION:
|
||||
holder.dialogAvatar.getHierarchy()
|
||||
.setImage(new BitmapDrawable(
|
||||
DisplayUtils.getRoundedBitmapFromVectorDrawableResource(context.getResources(),
|
||||
R.drawable.ic_people_group_white_24px)), 100, true);
|
||||
break;
|
||||
case ROOM_PUBLIC_CALL:
|
||||
case PUBLIC_CONVERSATION:
|
||||
holder.dialogAvatar.getHierarchy().setImage(new BitmapDrawable(DisplayUtils
|
||||
.getRoundedBitmapFromVectorDrawableResource(context.getResources(),
|
||||
R.drawable.ic_link_white_24px)), 100, true);
|
||||
|
@ -411,7 +411,7 @@ public class CallNotificationController extends BaseController {
|
||||
|
||||
private void loadAvatar() {
|
||||
switch (currentConversation.getType()) {
|
||||
case ROOM_TYPE_ONE_TO_ONE_CALL:
|
||||
case ONE_TO_ONE_CONVERSATION:
|
||||
avatarImageView.setVisibility(View.VISIBLE);
|
||||
|
||||
ImageRequest imageRequest =
|
||||
@ -463,12 +463,12 @@ public class CallNotificationController extends BaseController {
|
||||
}, UiThreadImmediateExecutorService.getInstance());
|
||||
|
||||
break;
|
||||
case ROOM_GROUP_CALL:
|
||||
case GROUP_CONVERSATION:
|
||||
avatarImageView.getHierarchy()
|
||||
.setImage(DisplayUtils.getRoundedDrawable(
|
||||
context.getDrawable(R.drawable.ic_people_group_white_24px))
|
||||
, 100, true);
|
||||
case ROOM_PUBLIC_CALL:
|
||||
case PUBLIC_CONVERSATION:
|
||||
avatarImageView.getHierarchy()
|
||||
.setImage(DisplayUtils.getRoundedDrawable(
|
||||
context.getDrawable(R.drawable.ic_people_group_white_24px))
|
||||
|
@ -312,7 +312,7 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
||||
private fun loadAvatarForStatusBar() {
|
||||
if (currentConversation != null && currentConversation?.type != null &&
|
||||
currentConversation?.type == Conversation.ConversationType
|
||||
.ROOM_TYPE_ONE_TO_ONE_CALL && activity != null && conversationVoiceCallMenuItem != null
|
||||
.ONE_TO_ONE_CONVERSATION && activity != null && conversationVoiceCallMenuItem != null
|
||||
) {
|
||||
val avatarSize = DisplayUtils.convertDpToPixel(
|
||||
conversationVoiceCallMenuItem?.icon!!
|
||||
@ -536,9 +536,8 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
||||
}
|
||||
|
||||
private fun checkReadOnlyState() {
|
||||
if (currentConversation != null) {
|
||||
if (currentConversation?.shouldShowLobby(
|
||||
conversationUser
|
||||
if (currentConversation != null && conversationUser != null) {
|
||||
if (currentConversation?.shouldShowLobby(conversationUser
|
||||
) == true || currentConversation?.conversationReadOnlyState != null && currentConversation?.conversationReadOnlyState == Conversation.ConversationReadOnlyState.CONVERSATION_READ_ONLY
|
||||
) {
|
||||
|
||||
@ -555,8 +554,8 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
||||
conversationVideoMenuItem?.icon?.alpha = 255
|
||||
}
|
||||
|
||||
if (currentConversation != null && currentConversation!!.shouldShowLobby
|
||||
(conversationUser)
|
||||
if (conversationUser != null && currentConversation != null && currentConversation!!
|
||||
.shouldShowLobby(conversationUser)
|
||||
) {
|
||||
messageInputView?.visibility = View.GONE
|
||||
} else {
|
||||
@ -567,8 +566,7 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
||||
}
|
||||
|
||||
private fun checkLobbyState() {
|
||||
if (currentConversation != null && currentConversation?.isLobbyViewApplicable(
|
||||
conversationUser
|
||||
if (currentConversation != null && conversationUser != null && currentConversation?.isLobbyViewApplicable(conversationUser
|
||||
) == true
|
||||
) {
|
||||
|
||||
@ -754,9 +752,11 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
||||
|
||||
override fun getTitle(): String? {
|
||||
if (currentConversation != null && currentConversation?.displayName != null) {
|
||||
return EmojiCompat.get()
|
||||
.process(currentConversation!!.displayName)
|
||||
return currentConversation!!.displayName?.let {
|
||||
EmojiCompat.get()
|
||||
.process(it)
|
||||
.toString()
|
||||
}
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
@ -1032,7 +1032,8 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
||||
return
|
||||
}
|
||||
|
||||
if (currentConversation != null && currentConversation!!.shouldShowLobby(conversationUser)) {
|
||||
if (currentConversation != null && conversationUser != null && currentConversation!!
|
||||
.shouldShowLobby(conversationUser)) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -1050,8 +1051,8 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
||||
lookingIntoFuture = true
|
||||
} else if (isFirstMessagesProcessing) {
|
||||
if (currentConversation != null) {
|
||||
globalLastKnownFutureMessageId = currentConversation!!.lastReadMessage
|
||||
globalLastKnownPastMessageId = currentConversation!!.lastReadMessage
|
||||
globalLastKnownFutureMessageId = currentConversation!!.lastReadMessageId
|
||||
globalLastKnownPastMessageId = currentConversation!!.lastReadMessageId
|
||||
fieldMap["includeLastKnown"] = 1
|
||||
}
|
||||
}
|
||||
@ -1188,7 +1189,7 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
||||
|
||||
val chatMessage = chatMessageList[i]
|
||||
chatMessage.isOneToOneConversation =
|
||||
currentConversation?.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
|
||||
currentConversation?.type == Conversation.ConversationType.ONE_TO_ONE_CONVERSATION
|
||||
chatMessage.isLinkPreviewAllowed = isLinkPreviewAllowed
|
||||
chatMessage.activeUser = conversationUser
|
||||
|
||||
@ -1258,7 +1259,7 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
||||
.actorId, -1
|
||||
) && adapter!!.getSameAuthorLastMessagesCount(chatMessage.actorId) % 5 > 0)
|
||||
chatMessage.isOneToOneConversation =
|
||||
(currentConversation?.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL)
|
||||
(currentConversation?.type == Conversation.ConversationType.ONE_TO_ONE_CONVERSATION)
|
||||
adapter?.addToStart(chatMessage, shouldScroll)
|
||||
}
|
||||
|
||||
@ -1447,7 +1448,7 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
||||
@Subscribe(threadMode = ThreadMode.BACKGROUND)
|
||||
fun onMessageEvent(userMentionClickEvent: UserMentionClickEvent) {
|
||||
if (currentConversation?.type != Conversation.ConversationType
|
||||
.ROOM_TYPE_ONE_TO_ONE_CALL || currentConversation?.name !=
|
||||
.ONE_TO_ONE_CONVERSATION || currentConversation?.name !=
|
||||
userMentionClickEvent.userId
|
||||
) {
|
||||
val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(
|
||||
@ -1482,11 +1483,14 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter
|
||||
)
|
||||
conversationIntent.putExtras(bundle)
|
||||
|
||||
if (roomOverall != null && roomOverall.ocs != null && roomOverall.ocs.data !=
|
||||
null && roomOverall.ocs.data.token != null) {
|
||||
ConductorRemapping.remapChatController(
|
||||
router, conversationUser.id,
|
||||
roomOverall.ocs.data.token, bundle, false
|
||||
roomOverall.ocs.data.token!!, bundle, false
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
conversationIntent.putExtras(bundle)
|
||||
|
@ -372,9 +372,9 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
Bundle bundle = new Bundle();
|
||||
Conversation.ConversationType roomType;
|
||||
if (isPublicCall) {
|
||||
roomType = Conversation.ConversationType.ROOM_PUBLIC_CALL;
|
||||
roomType = Conversation.ConversationType.PUBLIC_CONVERSATION;
|
||||
} else {
|
||||
roomType = Conversation.ConversationType.ROOM_GROUP_CALL;
|
||||
roomType = Conversation.ConversationType.GROUP_CONVERSATION;
|
||||
}
|
||||
|
||||
ArrayList<String> userIdsArray = new ArrayList<>(selectedUserIds);
|
||||
|
@ -63,7 +63,7 @@ import com.nextcloud.talk.jobs.LeaveConversationWorker
|
||||
import com.nextcloud.talk.models.database.UserEntity
|
||||
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.ROOM_PUBLIC_CALL
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType.PUBLIC_CONVERSATION
|
||||
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||
import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter
|
||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||
@ -253,8 +253,8 @@ class ConversationInfoController(args: Bundle) : BaseController(),
|
||||
|
||||
private fun setupWebinaryView() {
|
||||
if (conversationUser!!.hasSpreedFeatureCapability("webinary-lobby") && (conversation!!.type
|
||||
== Conversation.ConversationType.ROOM_GROUP_CALL || conversation!!.type ==
|
||||
Conversation.ConversationType.ROOM_PUBLIC_CALL) && conversation!!.canModerate(
|
||||
== Conversation.ConversationType.GROUP_CONVERSATION || conversation!!.type ==
|
||||
Conversation.ConversationType.PUBLIC_CONVERSATION) && conversation!!.canModerate(
|
||||
conversationUser
|
||||
)
|
||||
) {
|
||||
@ -270,8 +270,8 @@ class ConversationInfoController(args: Bundle) : BaseController(),
|
||||
startTimeView.setOnClickListener {
|
||||
MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
|
||||
val currentTimeCalendar = Calendar.getInstance()
|
||||
if (conversation!!.lobbyTimer != null && conversation!!.lobbyTimer != 0L) {
|
||||
currentTimeCalendar.timeInMillis = conversation!!.lobbyTimer * 1000
|
||||
if (conversation != null && conversation!!.lobbyTimer != null && conversation!!.lobbyTimer != 0L) {
|
||||
currentTimeCalendar.timeInMillis = conversation!!.lobbyTimer!! * 1000
|
||||
}
|
||||
|
||||
dateTimePicker(minDateTime = Calendar.getInstance(), requireFutureDateTime =
|
||||
@ -309,7 +309,7 @@ class ConversationInfoController(args: Bundle) : BaseController(),
|
||||
|
||||
if (conversation!!.lobbyTimer != null && conversation!!.lobbyTimer != java.lang.Long.MIN_VALUE && conversation!!.lobbyTimer != 0L) {
|
||||
startTimeView.setSummary(
|
||||
DateUtils.getLocalDateStringFromTimestampForLobby(conversation!!.lobbyTimer)
|
||||
conversation!!.lobbyTimer?.let { DateUtils.getLocalDateStringFromTimestampForLobby(it) }
|
||||
)
|
||||
} else {
|
||||
startTimeView.setSummary(R.string.nc_manual)
|
||||
@ -670,7 +670,7 @@ class ConversationInfoController(args: Bundle) : BaseController(),
|
||||
deleteConversationAction.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
if (Conversation.ConversationType.ROOM_SYSTEM == conversation!!.type) {
|
||||
if (Conversation.ConversationType.SYSTEM_CONVERSATION == conversation!!.type) {
|
||||
muteCalls.visibility = View.GONE
|
||||
}
|
||||
|
||||
@ -701,7 +701,7 @@ class ConversationInfoController(args: Bundle) : BaseController(),
|
||||
}
|
||||
|
||||
private fun setupGeneralSettings() {
|
||||
if (conversation != null) {
|
||||
if (conversation != null && conversationUser != null) {
|
||||
changeConversationName.value = conversation!!.displayName
|
||||
|
||||
if (conversation!!.isNameEditable(conversationUser)) {
|
||||
@ -710,12 +710,12 @@ class ConversationInfoController(args: Bundle) : BaseController(),
|
||||
changeConversationName.visibility = View.GONE
|
||||
}
|
||||
|
||||
favoriteConversationAction.value = conversation!!.isFavorite
|
||||
if (conversation!!.type.equals(ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) || conversation!!
|
||||
.type.equals(ConversationType.ROOM_SYSTEM)) {
|
||||
favoriteConversationAction.value = conversation!!.favorite
|
||||
if (conversation!!.type!!.equals(ConversationType.ONE_TO_ONE_CONVERSATION) || conversation!!
|
||||
.type!!.equals(ConversationType.SYSTEM_CONVERSATION)) {
|
||||
allowGuestsAction.visibility = View.GONE
|
||||
} else {
|
||||
allowGuestsAction.value = conversation!!.type == ROOM_PUBLIC_CALL
|
||||
allowGuestsAction.value = conversation!!.type == PUBLIC_CONVERSATION
|
||||
}
|
||||
|
||||
(allowGuestsAction.findViewById<View>(R.id.mp_checkable) as SwitchCompat)
|
||||
@ -813,7 +813,7 @@ class ConversationInfoController(args: Bundle) : BaseController(),
|
||||
}
|
||||
|
||||
private fun setProperNotificationValue(conversation: Conversation?) {
|
||||
if (conversation!!.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
|
||||
if (conversation!!.type == Conversation.ConversationType.ONE_TO_ONE_CONVERSATION) {
|
||||
// hack to see if we get mentioned always or just on mention
|
||||
if (conversationUser!!.hasSpreedFeatureCapability("mention-flag")) {
|
||||
messageNotificationLevel.value = "always"
|
||||
@ -827,7 +827,7 @@ class ConversationInfoController(args: Bundle) : BaseController(),
|
||||
|
||||
private fun loadConversationAvatar() {
|
||||
when (conversation!!.type) {
|
||||
Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (!TextUtils.isEmpty
|
||||
Conversation.ConversationType.ONE_TO_ONE_CONVERSATION -> if (!TextUtils.isEmpty
|
||||
(conversation!!.name)
|
||||
) {
|
||||
val draweeController = Fresco.newDraweeControllerBuilder()
|
||||
@ -844,21 +844,21 @@ class ConversationInfoController(args: Bundle) : BaseController(),
|
||||
.build()
|
||||
conversationAvatarImageView.controller = draweeController
|
||||
}
|
||||
Conversation.ConversationType.ROOM_GROUP_CALL -> conversationAvatarImageView.hierarchy.setPlaceholderImage(
|
||||
Conversation.ConversationType.GROUP_CONVERSATION -> conversationAvatarImageView.hierarchy.setPlaceholderImage(
|
||||
DisplayUtils
|
||||
.getRoundedBitmapDrawableFromVectorDrawableResource(
|
||||
resources,
|
||||
R.drawable.ic_people_group_white_24px
|
||||
)
|
||||
)
|
||||
Conversation.ConversationType.ROOM_PUBLIC_CALL -> conversationAvatarImageView.hierarchy.setPlaceholderImage(
|
||||
Conversation.ConversationType.PUBLIC_CONVERSATION -> conversationAvatarImageView.hierarchy.setPlaceholderImage(
|
||||
DisplayUtils
|
||||
.getRoundedBitmapDrawableFromVectorDrawableResource(
|
||||
resources,
|
||||
R.drawable.ic_link_white_24px
|
||||
)
|
||||
)
|
||||
Conversation.ConversationType.ROOM_SYSTEM -> {
|
||||
Conversation.ConversationType.SYSTEM_CONVERSATION -> {
|
||||
val layers = arrayOfNulls<Drawable>(2)
|
||||
layers[0] = context.getDrawable(R.drawable.ic_launcher_background)
|
||||
layers[1] = context.getDrawable(R.drawable.ic_launcher_foreground)
|
||||
|
@ -123,6 +123,9 @@ public class WebViewLoginController extends BaseController {
|
||||
|
||||
private WebViewFidoBridge webViewFidoBridge;
|
||||
|
||||
public WebViewLoginController() {
|
||||
}
|
||||
|
||||
public WebViewLoginController(String baseUrl, boolean isPasswordUpdate) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.isPasswordUpdate = isPasswordUpdate;
|
||||
|
@ -270,7 +270,7 @@ public class OperationsMenuController extends BaseController {
|
||||
invite = invitedGroups.get(0);
|
||||
}
|
||||
|
||||
if (conversationType.equals(Conversation.ConversationType.ROOM_PUBLIC_CALL) ||
|
||||
if (conversationType.equals(Conversation.ConversationType.PUBLIC_CONVERSATION) ||
|
||||
!currentUser.hasSpreedFeatureCapability("empty-group-room")) {
|
||||
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(currentUser.getBaseUrl(),
|
||||
"3", invite, conversationName);
|
||||
@ -314,7 +314,7 @@ public class OperationsMenuController extends BaseController {
|
||||
public void onNext(RoomOverall roomOverall) {
|
||||
conversation = roomOverall.getOcs().getData();
|
||||
if (conversationType.equals(
|
||||
Conversation.ConversationType.ROOM_PUBLIC_CALL)
|
||||
Conversation.ConversationType.PUBLIC_CONVERSATION)
|
||||
&& isGroupCallWorkaroundFinal) {
|
||||
performGroupCallWorkaround(credentials);
|
||||
} else {
|
||||
@ -490,7 +490,7 @@ public class OperationsMenuController extends BaseController {
|
||||
.getFeatures() != null && capabilitiesOverall.getOcs().getData()
|
||||
.getCapabilities().getSpreedCapability()
|
||||
.getFeatures().contains("chat-v2")) {
|
||||
if (conversation.isHasPassword() && conversation.isGuest()) {
|
||||
if (conversation.getHasPassword() && conversation.isGuest()) {
|
||||
eventBus.post(new BottomSheetLockEvent(true, 0,
|
||||
true, false));
|
||||
Bundle bundle = new Bundle();
|
||||
|
@ -27,7 +27,6 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.media.AudioAttributes;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
@ -171,12 +170,12 @@ public class NotificationWorker extends Worker {
|
||||
|
||||
intent.putExtra(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
|
||||
if (conversation.getType()
|
||||
.equals(Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) ||
|
||||
.equals(Conversation.ConversationType.ONE_TO_ONE_CONVERSATION) ||
|
||||
(!TextUtils.isEmpty(conversation.getObjectType()) && "share:password".equals
|
||||
(conversation.getObjectType()))) {
|
||||
context.startActivity(intent);
|
||||
} else {
|
||||
if (conversation.getType().equals(Conversation.ConversationType.ROOM_GROUP_CALL)) {
|
||||
if (conversation.getType().equals(Conversation.ConversationType.GROUP_CONVERSATION)) {
|
||||
conversationType = "group";
|
||||
} else {
|
||||
conversationType = "public";
|
||||
|
@ -43,7 +43,7 @@ import org.parceler.Parcel;
|
||||
|
||||
@Parcel
|
||||
@Data
|
||||
@JsonObject
|
||||
@JsonObject(serializeNullCollectionElements = true, serializeNullObjects = true)
|
||||
public class ChatMessage implements IMessage, MessageContentType, MessageContentType.Image {
|
||||
@JsonIgnore
|
||||
public boolean isGrouped;
|
||||
|
@ -1,173 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017 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.models.json.conversations;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonIgnore;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
import com.nextcloud.talk.models.database.UserEntity;
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage;
|
||||
import com.nextcloud.talk.models.json.converters.EnumLobbyStateConverter;
|
||||
import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter;
|
||||
import com.nextcloud.talk.models.json.converters.EnumParticipantTypeConverter;
|
||||
import com.nextcloud.talk.models.json.converters.EnumReadOnlyConversationConverter;
|
||||
import com.nextcloud.talk.models.json.converters.EnumRoomTypeConverter;
|
||||
import com.nextcloud.talk.models.json.participants.Participant;
|
||||
import java.util.HashMap;
|
||||
import lombok.Data;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
@Parcel
|
||||
@Data
|
||||
@JsonObject
|
||||
public class Conversation {
|
||||
@JsonField(name = "id")
|
||||
public String conversationId;
|
||||
@JsonField(name = "token")
|
||||
public String token;
|
||||
@JsonField(name = "name")
|
||||
public String name;
|
||||
@JsonField(name = "displayName")
|
||||
public String displayName;
|
||||
@JsonField(name = "type", typeConverter = EnumRoomTypeConverter.class)
|
||||
public ConversationType type;
|
||||
@JsonField(name = "count")
|
||||
public long count;
|
||||
@JsonField(name = "lastPing")
|
||||
public long lastPing;
|
||||
@JsonField(name = "numGuests")
|
||||
public long numberOfGuests;
|
||||
@JsonField(name = "guestList")
|
||||
public HashMap<String, HashMap<String, Object>> guestList;
|
||||
@JsonField(name = "participants")
|
||||
public HashMap<String, HashMap<String, Object>> participants;
|
||||
@JsonField(name = "participantType", typeConverter = EnumParticipantTypeConverter.class)
|
||||
public Participant.ParticipantType participantType;
|
||||
@JsonField(name = "hasPassword")
|
||||
public boolean hasPassword;
|
||||
@JsonField(name = "sessionId")
|
||||
public String sessionId;
|
||||
public String password;
|
||||
@JsonField(name = "isFavorite")
|
||||
public boolean isFavorite;
|
||||
@JsonField(name = "lastActivity")
|
||||
public long lastActivity;
|
||||
@JsonField(name = "unreadMessages")
|
||||
public int unreadMessages;
|
||||
@JsonField(name = "unreadMention")
|
||||
public boolean unreadMention;
|
||||
@JsonField(name = "lastMessage")
|
||||
public ChatMessage lastMessage;
|
||||
@JsonField(name = "objectType")
|
||||
public String objectType;
|
||||
@JsonField(name = "notificationLevel", typeConverter = EnumNotificationLevelConverter.class)
|
||||
public NotificationLevel notificationLevel;
|
||||
@JsonField(name = "readOnly", typeConverter = EnumReadOnlyConversationConverter.class)
|
||||
public ConversationReadOnlyState conversationReadOnlyState;
|
||||
@JsonField(name = "lobbyState", typeConverter = EnumLobbyStateConverter.class)
|
||||
public LobbyState lobbyState;
|
||||
@JsonField(name = "lobbyTimer")
|
||||
public Long lobbyTimer;
|
||||
@JsonField(name = "lastReadMessage")
|
||||
public int lastReadMessage;
|
||||
public boolean updating;
|
||||
|
||||
public boolean isPublic() {
|
||||
return (ConversationType.ROOM_PUBLIC_CALL.equals(type));
|
||||
}
|
||||
|
||||
public boolean isGuest() {
|
||||
return (Participant.ParticipantType.GUEST.equals(participantType) ||
|
||||
Participant.ParticipantType.USER_FOLLOWING_LINK.equals(participantType));
|
||||
}
|
||||
|
||||
private boolean isLockedOneToOne(UserEntity conversationUser) {
|
||||
return (getType() == ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
|
||||
&& conversationUser.hasSpreedFeatureCapability("locked-one-to-one-rooms"));
|
||||
}
|
||||
|
||||
public boolean canModerate(UserEntity conversationUser) {
|
||||
return ((Participant.ParticipantType.OWNER.equals(participantType)
|
||||
|| Participant.ParticipantType.MODERATOR.equals(participantType)) && !isLockedOneToOne(
|
||||
conversationUser));
|
||||
}
|
||||
|
||||
public boolean shouldShowLobby(UserEntity conversationUser) {
|
||||
return LobbyState.LOBBY_STATE_MODERATORS_ONLY.equals(getLobbyState()) && !canModerate(
|
||||
conversationUser);
|
||||
}
|
||||
|
||||
public boolean isLobbyViewApplicable(UserEntity conversationUser) {
|
||||
return !canModerate(conversationUser) && (getType() == ConversationType.ROOM_GROUP_CALL
|
||||
|| getType() == ConversationType.ROOM_PUBLIC_CALL);
|
||||
}
|
||||
|
||||
public boolean isNameEditable(UserEntity conversationUser) {
|
||||
return (canModerate(conversationUser) && !ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL.equals(
|
||||
type));
|
||||
}
|
||||
|
||||
public boolean canLeave(UserEntity conversationUser) {
|
||||
return !canModerate(conversationUser) || (getType()
|
||||
!= ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL && getParticipants().size() > 1);
|
||||
}
|
||||
|
||||
public String getDeleteWarningMessage() {
|
||||
Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
|
||||
if (getType() == ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
|
||||
return String.format(resources.getString(R.string.nc_delete_conversation_one2one),
|
||||
getDisplayName());
|
||||
} else if (getParticipants().size() > 1) {
|
||||
return resources.getString(R.string.nc_delete_conversation_more);
|
||||
}
|
||||
|
||||
return resources.getString(R.string.nc_delete_conversation_default);
|
||||
}
|
||||
|
||||
public enum NotificationLevel {
|
||||
DEFAULT,
|
||||
ALWAYS,
|
||||
MENTION,
|
||||
NEVER
|
||||
}
|
||||
|
||||
public enum LobbyState {
|
||||
LOBBY_STATE_ALL_PARTICIPANTS,
|
||||
LOBBY_STATE_MODERATORS_ONLY
|
||||
}
|
||||
|
||||
public enum ConversationReadOnlyState {
|
||||
CONVERSATION_READ_WRITE,
|
||||
CONVERSATION_READ_ONLY
|
||||
}
|
||||
|
||||
@Parcel
|
||||
public enum ConversationType {
|
||||
DUMMY,
|
||||
ROOM_TYPE_ONE_TO_ONE_CALL,
|
||||
ROOM_GROUP_CALL,
|
||||
ROOM_PUBLIC_CALL,
|
||||
ROOM_SYSTEM
|
||||
}
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
/*
|
||||
*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Mario Danic
|
||||
* Copyright (C) 2017 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.models.json.conversations
|
||||
|
||||
import androidx.annotation.NonNull
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField
|
||||
import com.bluelinelabs.logansquare.annotation.JsonIgnore
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.models.database.UserEntity
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
import com.nextcloud.talk.models.json.converters.EnumLobbyStateConverter
|
||||
import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter
|
||||
import com.nextcloud.talk.models.json.converters.EnumParticipantTypeConverter
|
||||
import com.nextcloud.talk.models.json.converters.EnumReadOnlyConversationConverter
|
||||
import com.nextcloud.talk.models.json.converters.EnumRoomTypeConverter
|
||||
import com.nextcloud.talk.models.json.participants.Participant
|
||||
import lombok.Data
|
||||
import org.parceler.Parcel
|
||||
import org.parceler.ParcelConstructor
|
||||
import java.util.HashMap
|
||||
|
||||
@Parcel
|
||||
@Data
|
||||
@JsonObject(serializeNullCollectionElements = true, serializeNullObjects = true)
|
||||
class Conversation {
|
||||
@JsonIgnore
|
||||
@NonNull
|
||||
var user: Long = 0L
|
||||
@JsonField(name = ["id"])
|
||||
var conversationId: String = ""
|
||||
@JsonField(name = ["token"])
|
||||
var token: String? = null
|
||||
@JsonField(name = ["name"])
|
||||
var name: String? = null
|
||||
@JsonField(name = ["displayName"])
|
||||
var displayName: String? = null
|
||||
@JsonField(name = ["type"], typeConverter = EnumRoomTypeConverter::class)
|
||||
var type: ConversationType? = null
|
||||
@JsonField(name = ["count"])
|
||||
var count: Long = 0
|
||||
/*@JsonField(name = ["lastPing"])
|
||||
var lastPing: Long = 0*/
|
||||
@JsonField(name = ["numGuests"])
|
||||
var numberOfGuests: Long = 0
|
||||
/*@JsonField(name = ["guestList"])
|
||||
var guestList: HashMap<String, HashMap<String, Any>>? = null*/
|
||||
@JsonField(name = ["participants"])
|
||||
var participants: HashMap<String, HashMap<String, Any>>? = null
|
||||
@JsonField(name = ["participantType"], typeConverter = EnumParticipantTypeConverter::class)
|
||||
var participantType: Participant.ParticipantType? = null
|
||||
@JsonField(name = ["hasPassword"])
|
||||
var hasPassword: Boolean = false
|
||||
@JsonField(name = ["sessionId"])
|
||||
var sessionId: String? = null
|
||||
@JsonIgnore var password: String? = null
|
||||
@JsonField(name = ["isFavorite"])
|
||||
var favorite: Boolean = false
|
||||
@JsonField(name = ["lastActivity"])
|
||||
var lastActivity: Long = 0
|
||||
@JsonField(name = ["unreadMessages"])
|
||||
var unreadMessages: Int = 0
|
||||
@JsonField(name = ["unreadMention"])
|
||||
var unreadMention: Boolean = false
|
||||
@JsonField(name = ["lastMessage"])
|
||||
var lastMessage: ChatMessage? = null
|
||||
@JsonField(name = ["objectType"])
|
||||
var objectType: String? = null
|
||||
@JsonField(name = ["notificationLevel"], typeConverter = EnumNotificationLevelConverter::class)
|
||||
var notificationLevel: NotificationLevel? = null
|
||||
@JsonField(name = ["readOnly"], typeConverter = EnumReadOnlyConversationConverter::class)
|
||||
var conversationReadOnlyState:
|
||||
ConversationReadOnlyState? = null
|
||||
@JsonField(name = ["lobbyState"], typeConverter = EnumLobbyStateConverter::class)
|
||||
var lobbyState: LobbyState? = null
|
||||
@JsonField(name = ["lobbyTimer"])
|
||||
var lobbyTimer: Long? = 0
|
||||
@JsonField(name = ["lastReadMessageId"])
|
||||
var lastReadMessageId: Int = 0
|
||||
var changing: Boolean = false
|
||||
|
||||
val isPublic: Boolean = ConversationType.PUBLIC_CONVERSATION == type
|
||||
val isGuest: Boolean =
|
||||
Participant.ParticipantType.GUEST == participantType ||
|
||||
Participant.ParticipantType.USER_FOLLOWING_LINK == participantType
|
||||
|
||||
val deleteWarningMessage: String
|
||||
get() {
|
||||
val resources = NextcloudTalkApplication.sharedApplication!!.resources
|
||||
if (type == ConversationType.ONE_TO_ONE_CONVERSATION) {
|
||||
return String.format(
|
||||
resources.getString(R.string.nc_delete_conversation_one2one),
|
||||
displayName!!
|
||||
)
|
||||
} else if (participants!!.size > 1) {
|
||||
return resources.getString(R.string.nc_delete_conversation_more)
|
||||
}
|
||||
|
||||
return resources.getString(R.string.nc_delete_conversation_default)
|
||||
}
|
||||
|
||||
private fun isLockedOneToOne(conversationUser: UserEntity): Boolean {
|
||||
return type == ConversationType.ONE_TO_ONE_CONVERSATION && conversationUser
|
||||
.hasSpreedFeatureCapability(
|
||||
"locked-one-to-one-rooms"
|
||||
)
|
||||
}
|
||||
|
||||
fun canModerate(conversationUser: UserEntity): Boolean {
|
||||
return (Participant.ParticipantType.OWNER == participantType || Participant.ParticipantType.MODERATOR == participantType) && !isLockedOneToOne(
|
||||
conversationUser
|
||||
)
|
||||
}
|
||||
|
||||
fun shouldShowLobby(conversationUser: UserEntity): Boolean {
|
||||
return LobbyState.LOBBY_STATE_MODERATORS_ONLY == lobbyState && !canModerate(
|
||||
conversationUser
|
||||
)
|
||||
}
|
||||
|
||||
fun isLobbyViewApplicable(conversationUser: UserEntity): Boolean {
|
||||
return !canModerate(
|
||||
conversationUser
|
||||
) && (type == ConversationType.GROUP_CONVERSATION || type == ConversationType.PUBLIC_CONVERSATION)
|
||||
}
|
||||
|
||||
fun isNameEditable(conversationUser: UserEntity): Boolean {
|
||||
return canModerate(conversationUser) && ConversationType.ONE_TO_ONE_CONVERSATION != type
|
||||
}
|
||||
|
||||
fun canLeave(conversationUser: UserEntity): Boolean {
|
||||
return !canModerate(
|
||||
conversationUser
|
||||
) || type != ConversationType.ONE_TO_ONE_CONVERSATION && participants!!.size > 1
|
||||
}
|
||||
|
||||
enum class NotificationLevel {
|
||||
DEFAULT,
|
||||
ALWAYS,
|
||||
MENTION,
|
||||
NEVER
|
||||
}
|
||||
|
||||
enum class LobbyState {
|
||||
LOBBY_STATE_ALL_PARTICIPANTS,
|
||||
LOBBY_STATE_MODERATORS_ONLY
|
||||
}
|
||||
|
||||
enum class ConversationReadOnlyState {
|
||||
CONVERSATION_READ_WRITE,
|
||||
CONVERSATION_READ_ONLY
|
||||
}
|
||||
|
||||
@Parcel
|
||||
enum class ConversationType @ParcelConstructor constructor(val value: Int = 1) {
|
||||
ONE_TO_ONE_CONVERSATION(1),
|
||||
GROUP_CONVERSATION(2),
|
||||
PUBLIC_CONVERSATION(3),
|
||||
SYSTEM_CONVERSATION(4)
|
||||
}
|
||||
}
|
@ -28,33 +28,31 @@ public class EnumRoomTypeConverter extends IntBasedTypeConverter<Conversation.Co
|
||||
public Conversation.ConversationType getFromInt(int i) {
|
||||
switch (i) {
|
||||
case 1:
|
||||
return Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL;
|
||||
return Conversation.ConversationType.ONE_TO_ONE_CONVERSATION;
|
||||
case 2:
|
||||
return Conversation.ConversationType.ROOM_GROUP_CALL;
|
||||
return Conversation.ConversationType.GROUP_CONVERSATION;
|
||||
case 3:
|
||||
return Conversation.ConversationType.ROOM_PUBLIC_CALL;
|
||||
return Conversation.ConversationType.PUBLIC_CONVERSATION;
|
||||
case 4:
|
||||
return Conversation.ConversationType.ROOM_SYSTEM;
|
||||
return Conversation.ConversationType.SYSTEM_CONVERSATION;
|
||||
default:
|
||||
return Conversation.ConversationType.DUMMY;
|
||||
return Conversation.ConversationType.ONE_TO_ONE_CONVERSATION;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int convertToInt(Conversation.ConversationType object) {
|
||||
switch (object) {
|
||||
case DUMMY:
|
||||
return 0;
|
||||
case ROOM_TYPE_ONE_TO_ONE_CALL:
|
||||
case ONE_TO_ONE_CONVERSATION:
|
||||
return 1;
|
||||
case ROOM_GROUP_CALL:
|
||||
case GROUP_CONVERSATION:
|
||||
return 2;
|
||||
case ROOM_PUBLIC_CALL:
|
||||
case PUBLIC_CONVERSATION:
|
||||
return 3;
|
||||
case ROOM_SYSTEM:
|
||||
case SYSTEM_CONVERSATION:
|
||||
return 4;
|
||||
default:
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.data.repository
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.map
|
||||
import com.nextcloud.talk.models.database.UserEntity
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.nextcloud.talk.newarch.domain.repository.NextcloudTalkOfflineRepository
|
||||
import com.nextcloud.talk.newarch.local.db.TalkDatabase
|
||||
import com.nextcloud.talk.newarch.local.models.toConversation
|
||||
import com.nextcloud.talk.newarch.local.models.toConversationEntity
|
||||
|
||||
class NextcloudTalkOfflineRepositoryImpl(val nextcloudTalkDatabase: TalkDatabase) :
|
||||
NextcloudTalkOfflineRepository {
|
||||
override suspend fun setChangingValueForConversation(
|
||||
userId: Long,
|
||||
conversationId: String,
|
||||
changing: Boolean
|
||||
) {
|
||||
nextcloudTalkDatabase.conversationsDao()
|
||||
.updateChangingValueForConversation(userId, conversationId, changing)
|
||||
}
|
||||
|
||||
override suspend fun setFavoriteValueForConversation(
|
||||
userId: Long,
|
||||
conversationId: String,
|
||||
favorite: Boolean
|
||||
) {
|
||||
nextcloudTalkDatabase.conversationsDao()
|
||||
.updateFavoriteValueForConversation(userId, conversationId, favorite)
|
||||
}
|
||||
|
||||
override suspend fun deleteConversation(
|
||||
userId: Long,
|
||||
conversationId: String
|
||||
) {
|
||||
nextcloudTalkDatabase.conversationsDao()
|
||||
.deleteConversation(userId, conversationId)
|
||||
}
|
||||
|
||||
override fun getConversationsForUser(user: UserEntity): LiveData<List<Conversation>> {
|
||||
return nextcloudTalkDatabase.conversationsDao()
|
||||
.getConversationsForUser(user.id)
|
||||
.map { data ->
|
||||
data.map {
|
||||
it.toConversation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun getDatabase(): TalkDatabase {
|
||||
return nextcloudTalkDatabase
|
||||
}
|
||||
|
||||
override suspend fun clearConversationsForUser(user: UserEntity) {
|
||||
nextcloudTalkDatabase.conversationsDao()
|
||||
.clearConversationsForUser(user.id)
|
||||
}
|
||||
|
||||
override suspend fun saveConversationsForUser(
|
||||
user: UserEntity,
|
||||
conversations: List<Conversation>
|
||||
) {
|
||||
nextcloudTalkDatabase.conversationsDao()
|
||||
.updateConversationsForUser(
|
||||
user.id,
|
||||
conversations.map {
|
||||
it.toConversationEntity()
|
||||
}.toTypedArray()
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun deleteConversationForUserWithTimestamp(
|
||||
user: UserEntity,
|
||||
timestamp: Long
|
||||
) {
|
||||
nextcloudTalkDatabase.conversationsDao()
|
||||
.deleteConversationsForUserWithTimestamp(user.id, timestamp)
|
||||
}
|
||||
}
|
@ -33,15 +33,21 @@ class NextcloudTalkRepositoryImpl(private val apiService: ApiService) : Nextclou
|
||||
user: UserEntity,
|
||||
conversation: Conversation
|
||||
): GenericOverall {
|
||||
return apiService.deleteConversation(user.getCredentials(), ApiUtils.getRoom(user.baseUrl, conversation.token))
|
||||
return apiService.deleteConversation(
|
||||
user.getCredentials(), ApiUtils.getRoom(user.baseUrl, conversation.token)
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun leaveConversationForUser(
|
||||
user: UserEntity,
|
||||
conversation: Conversation
|
||||
): GenericOverall {
|
||||
return apiService.leaveConversation(user.getCredentials(), ApiUtils.getUrlForRemoveSelfFromRoom(user
|
||||
.baseUrl, conversation.token))
|
||||
return apiService.leaveConversation(
|
||||
user.getCredentials(), ApiUtils.getUrlForRemoveSelfFromRoom(
|
||||
user
|
||||
.baseUrl, conversation.token
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun setFavoriteValueForConversation(
|
||||
@ -66,6 +72,7 @@ class NextcloudTalkRepositoryImpl(private val apiService: ApiService) : Nextclou
|
||||
return apiService.getConversations(
|
||||
user.getCredentials(),
|
||||
ApiUtils.getUrlForGetRooms(user.baseUrl)
|
||||
).ocs.data
|
||||
)
|
||||
.ocs.data
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ package com.nextcloud.talk.newarch.data.source.remote
|
||||
|
||||
import com.nextcloud.talk.models.json.conversations.RoomsOverall
|
||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||
import io.reactivex.Observable
|
||||
import retrofit2.http.DELETE
|
||||
import retrofit2.http.GET
|
||||
import retrofit2.http.Header
|
||||
|
@ -31,7 +31,6 @@ import com.nextcloud.talk.newarch.data.repository.NextcloudTalkRepositoryImpl
|
||||
import com.nextcloud.talk.newarch.data.source.remote.ApiErrorHandler
|
||||
import com.nextcloud.talk.newarch.data.source.remote.ApiService
|
||||
import com.nextcloud.talk.newarch.domain.repository.NextcloudTalkRepository
|
||||
import com.nextcloud.talk.newarch.domain.usecases.GetConversationsUseCase
|
||||
import com.nextcloud.talk.newarch.utils.NetworkUtils
|
||||
import com.nextcloud.talk.newarch.utils.NetworkUtils.GetProxyRunnable
|
||||
import com.nextcloud.talk.newarch.utils.NetworkUtils.MagicAuthenticator
|
||||
@ -81,6 +80,7 @@ val NetworkModule = module {
|
||||
single { createOkHttpClient(androidContext(), get(), get(), get(), get(), get(), get(), get()) }
|
||||
factory { createApiErrorHandler() }
|
||||
single { createNextcloudTalkRepository(get()) }
|
||||
|
||||
}
|
||||
|
||||
fun createCookieManager(): CookieManager {
|
||||
@ -253,10 +253,3 @@ fun createService(retrofit: Retrofit): ApiService {
|
||||
fun createNextcloudTalkRepository(apiService: ApiService): NextcloudTalkRepository {
|
||||
return NextcloudTalkRepositoryImpl(apiService)
|
||||
}
|
||||
|
||||
fun createGetConversationsUseCase(
|
||||
nextcloudTalkRepository: NextcloudTalkRepository,
|
||||
apiErrorHandler: ApiErrorHandler
|
||||
): GetConversationsUseCase {
|
||||
return GetConversationsUseCase(nextcloudTalkRepository, apiErrorHandler)
|
||||
}
|
||||
|
@ -21,8 +21,12 @@
|
||||
package com.nextcloud.talk.newarch.di.module
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Room
|
||||
import com.nextcloud.talk.R.string
|
||||
import com.nextcloud.talk.models.database.Models
|
||||
import com.nextcloud.talk.newarch.data.repository.NextcloudTalkOfflineRepositoryImpl
|
||||
import com.nextcloud.talk.newarch.domain.repository.NextcloudTalkOfflineRepository
|
||||
import com.nextcloud.talk.newarch.local.db.TalkDatabase
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||
import io.requery.Persistable
|
||||
@ -31,6 +35,7 @@ import io.requery.reactivex.ReactiveEntityStore
|
||||
import io.requery.reactivex.ReactiveSupport
|
||||
import io.requery.sql.EntityDataStore
|
||||
import net.orange_box.storebox.StoreBox
|
||||
import org.koin.android.ext.koin.androidApplication
|
||||
import org.koin.android.ext.koin.androidContext
|
||||
import org.koin.dsl.module
|
||||
|
||||
@ -39,6 +44,21 @@ val StorageModule = module {
|
||||
single { createSqlCipherDatabaseSource(androidContext()) }
|
||||
single { createDataStore(get()) }
|
||||
single { createUserUtils(get()) }
|
||||
single { createNextcloudTalkOfflineRepository(get()) }
|
||||
single { TalkDatabase.getInstance(androidApplication()) }
|
||||
single { get<TalkDatabase>().conversationsDao() }
|
||||
}
|
||||
|
||||
fun createNextcloudTalkOfflineRepository(database: TalkDatabase): NextcloudTalkOfflineRepository {
|
||||
return NextcloudTalkOfflineRepositoryImpl(database)
|
||||
}
|
||||
|
||||
fun createDatabase(context: Context): TalkDatabase {
|
||||
return Room.databaseBuilder(
|
||||
context,
|
||||
TalkDatabase::class.java, "talk.db"
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
fun createPreferences(context: Context): AppPreferences {
|
||||
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.domain.repository
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.nextcloud.talk.models.database.UserEntity
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
|
||||
interface NextcloudTalkOfflineRepository {
|
||||
fun getConversationsForUser(user: UserEntity): LiveData<List<Conversation>>
|
||||
suspend fun clearConversationsForUser(user: UserEntity)
|
||||
suspend fun saveConversationsForUser(
|
||||
user: UserEntity,
|
||||
conversations: List<Conversation>
|
||||
)
|
||||
|
||||
suspend fun setChangingValueForConversation(
|
||||
userId: Long,
|
||||
conversationId: String,
|
||||
changing: Boolean
|
||||
)
|
||||
|
||||
suspend fun setFavoriteValueForConversation(
|
||||
userId: Long,
|
||||
conversationId: String,
|
||||
favorite: Boolean
|
||||
)
|
||||
|
||||
suspend fun deleteConversation(
|
||||
userId: Long,
|
||||
conversationId: String
|
||||
)
|
||||
|
||||
suspend fun deleteConversationForUserWithTimestamp(
|
||||
user: UserEntity,
|
||||
timestamp: Long
|
||||
)
|
||||
}
|
@ -31,6 +31,14 @@ interface NextcloudTalkRepository {
|
||||
conversation: Conversation,
|
||||
favorite: Boolean
|
||||
): GenericOverall
|
||||
suspend fun deleteConversationForUser(user: UserEntity, conversation: Conversation) : GenericOverall
|
||||
suspend fun leaveConversationForUser(userEntity: UserEntity, conversation: Conversation) : GenericOverall
|
||||
|
||||
suspend fun deleteConversationForUser(
|
||||
user: UserEntity,
|
||||
conversation: Conversation
|
||||
): GenericOverall
|
||||
|
||||
suspend fun leaveConversationForUser(
|
||||
userEntity: UserEntity,
|
||||
conversation: Conversation
|
||||
): GenericOverall
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ package com.nextcloud.talk.newarch.domain.usecases.base
|
||||
import com.nextcloud.talk.newarch.data.model.ErrorModel
|
||||
|
||||
interface UseCaseResponse<Type> {
|
||||
fun onSuccess(result: Type)
|
||||
suspend fun onSuccess(result: Type)
|
||||
fun onError(errorModel: ErrorModel?)
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@ package com.nextcloud.talk.newarch.features.conversationsList
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.nextcloud.talk.newarch.domain.repository.NextcloudTalkOfflineRepository
|
||||
import com.nextcloud.talk.newarch.domain.usecases.DeleteConversationUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.GetConversationsUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.LeaveConversationUseCase
|
||||
@ -35,12 +36,15 @@ class ConversationListViewModelFactory constructor(
|
||||
private val setConversationFavoriteValueUseCase: SetConversationFavoriteValueUseCase,
|
||||
private val leaveConversationUseCase: LeaveConversationUseCase,
|
||||
private val deleteConversationUseCase: DeleteConversationUseCase,
|
||||
private val userUtils: UserUtils
|
||||
private val userUtils: UserUtils,
|
||||
private val offlineRepository: NextcloudTalkOfflineRepository
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
|
||||
return ConversationsListViewModel(application, conversationsUseCase,
|
||||
return ConversationsListViewModel(
|
||||
application, conversationsUseCase,
|
||||
setConversationFavoriteValueUseCase, leaveConversationUseCase, deleteConversationUseCase,
|
||||
userUtils) as T
|
||||
userUtils, offlineRepository
|
||||
) as T
|
||||
}
|
||||
}
|
||||
|
@ -75,6 +75,7 @@ import kotlinx.android.synthetic.main.view_states.view.errorStateImageView
|
||||
import kotlinx.android.synthetic.main.view_states.view.errorStateTextView
|
||||
import kotlinx.android.synthetic.main.view_states.view.loadingStateView
|
||||
import kotlinx.android.synthetic.main.view_states.view.stateWithMessageView
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder
|
||||
import org.koin.android.ext.android.inject
|
||||
import org.parceler.Parcels
|
||||
import java.util.ArrayList
|
||||
@ -180,6 +181,7 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
||||
container: ViewGroup
|
||||
): View {
|
||||
setHasOptionsMenu(true)
|
||||
actionBar?.show()
|
||||
|
||||
viewModel = viewModelProvider(factory).get(ConversationsListViewModel::class.java)
|
||||
viewModel.apply {
|
||||
@ -243,10 +245,29 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
||||
}
|
||||
})
|
||||
|
||||
conversationsLiveListData.observe(this@ConversationsListView, Observer {
|
||||
conversationsLiveData.observe(this@ConversationsListView, Observer {
|
||||
if (it.size == 0) {
|
||||
viewState.value = LOADED_EMPTY
|
||||
} else {
|
||||
viewState.value = LOADED
|
||||
}
|
||||
val sortedConversationsList = it.toMutableList()
|
||||
|
||||
sortedConversationsList.sortWith(Comparator { conversation1, conversation2 ->
|
||||
CompareToBuilder()
|
||||
.append(conversation2.favorite, conversation1.favorite)
|
||||
.append(conversation2.lastActivity, conversation1.lastActivity)
|
||||
.toComparison()
|
||||
})
|
||||
|
||||
val newConversations = mutableListOf<ConversationItem>()
|
||||
for (conversation in it) {
|
||||
newConversations.add(ConversationItem(conversation, viewModel.currentUser, activity))
|
||||
for (conversation in sortedConversationsList) {
|
||||
newConversations.add(
|
||||
ConversationItem(
|
||||
conversation, viewModel.currentUserLiveData.value,
|
||||
activity
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
recyclerViewAdapter.updateDataSet(newConversations as List<IFlexible<ViewHolder>>?)
|
||||
@ -313,7 +334,7 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
||||
var displayName =
|
||||
(recyclerViewAdapter.getItem(position) as ConversationItem).model.displayName
|
||||
|
||||
if (displayName.length > 8) {
|
||||
if (displayName!!.length > 8) {
|
||||
displayName = displayName.substring(0, 4) + "..."
|
||||
}
|
||||
|
||||
@ -394,12 +415,12 @@ class ConversationsListView : BaseView(), OnQueryTextListener,
|
||||
val conversation = (clickedItem as ConversationItem).model
|
||||
|
||||
val bundle = Bundle()
|
||||
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, viewModel.currentUser)
|
||||
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, viewModel.currentUserLiveData.value)
|
||||
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, conversation.token)
|
||||
bundle.putString(BundleKeys.KEY_ROOM_ID, conversation.conversationId)
|
||||
bundle.putParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION, Parcels.wrap(conversation))
|
||||
ConductorRemapping.remapChatController(
|
||||
router, viewModel.currentUser.id, conversation.token,
|
||||
router, viewModel.currentUserLiveData.value!!.id, conversation!!.token!!,
|
||||
bundle, false
|
||||
)
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Drawable
|
||||
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.Transformations
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.facebook.common.executors.UiThreadImmediateExecutorService
|
||||
import com.facebook.common.references.CloseableReference
|
||||
@ -42,22 +43,19 @@ import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||
import com.nextcloud.talk.newarch.conversationsList.mvp.BaseViewModel
|
||||
import com.nextcloud.talk.newarch.data.model.ErrorModel
|
||||
import com.nextcloud.talk.newarch.domain.repository.NextcloudTalkOfflineRepository
|
||||
import com.nextcloud.talk.newarch.domain.usecases.DeleteConversationUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.GetConversationsUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.LeaveConversationUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.SetConversationFavoriteValueUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse
|
||||
import com.nextcloud.talk.newarch.utils.ViewState
|
||||
import com.nextcloud.talk.newarch.utils.ViewState.FAILED
|
||||
import com.nextcloud.talk.newarch.utils.ViewState.INITIAL_LOAD
|
||||
import com.nextcloud.talk.newarch.utils.ViewState.LOADED
|
||||
import com.nextcloud.talk.newarch.utils.ViewState.LOADED_EMPTY
|
||||
import com.nextcloud.talk.newarch.utils.ViewState.LOADING
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import com.nextcloud.talk.utils.DisplayUtils
|
||||
import com.nextcloud.talk.utils.ShareUtils
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.parameter.parametersOf
|
||||
|
||||
class ConversationsListViewModel constructor(
|
||||
@ -66,15 +64,18 @@ class ConversationsListViewModel constructor(
|
||||
private val setConversationFavoriteValueUseCase: SetConversationFavoriteValueUseCase,
|
||||
private val leaveConversationUseCase: LeaveConversationUseCase,
|
||||
private val deleteConversationUseCase: DeleteConversationUseCase,
|
||||
private val userUtils: UserUtils
|
||||
private val userUtils: UserUtils,
|
||||
private val offlineRepository: NextcloudTalkOfflineRepository
|
||||
) : BaseViewModel<ConversationsListView>(application) {
|
||||
|
||||
private var conversations: MutableList<Conversation> = mutableListOf()
|
||||
val conversationsLiveListData = MutableLiveData<List<Conversation>>()
|
||||
val viewState = MutableLiveData<ViewState>(INITIAL_LOAD)
|
||||
val viewState = MutableLiveData<ViewState>(LOADING)
|
||||
var messageData: String? = null
|
||||
val searchQuery = MutableLiveData<String>()
|
||||
var currentUser: UserEntity = userUtils.currentUser
|
||||
val currentUserLiveData: MutableLiveData<UserEntity> = MutableLiveData()
|
||||
val conversationsLiveData = Transformations.switchMap(currentUserLiveData) {
|
||||
offlineRepository.getConversationsForUser(it)
|
||||
}
|
||||
|
||||
var currentUserAvatar: MutableLiveData<Drawable> = MutableLiveData()
|
||||
get() {
|
||||
if (field.value == null) {
|
||||
@ -85,48 +86,53 @@ class ConversationsListViewModel constructor(
|
||||
}
|
||||
|
||||
fun leaveConversation(conversation: Conversation) {
|
||||
viewModelScope.launch {
|
||||
setConversationUpdateStatus(conversation, true)
|
||||
|
||||
leaveConversationUseCase.invoke(viewModelScope, parametersOf(currentUser, conversation),
|
||||
}
|
||||
leaveConversationUseCase.invoke(viewModelScope, parametersOf(
|
||||
currentUserLiveData.value,
|
||||
conversation
|
||||
),
|
||||
object : UseCaseResponse<GenericOverall> {
|
||||
override fun onSuccess(result: GenericOverall) {
|
||||
// TODO: Use binary search to find the right room
|
||||
conversations.find { it.conversationId == conversation.conversationId }
|
||||
?.let {
|
||||
conversations.remove(it)
|
||||
conversationsLiveListData.value = conversations
|
||||
if (conversations.isEmpty()) {
|
||||
viewState.value = LOADED_EMPTY
|
||||
}
|
||||
}
|
||||
override suspend fun onSuccess(result: GenericOverall) {
|
||||
offlineRepository.deleteConversation(
|
||||
currentUserLiveData.value!!.id, conversation
|
||||
.conversationId
|
||||
)
|
||||
}
|
||||
|
||||
override fun onError(errorModel: ErrorModel?) {
|
||||
messageData = errorModel?.getErrorMessage()
|
||||
viewModelScope.launch {
|
||||
setConversationUpdateStatus(conversation, false)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun deleteConversation(conversation: Conversation) {
|
||||
viewModelScope.launch {
|
||||
setConversationUpdateStatus(conversation, true)
|
||||
}
|
||||
|
||||
deleteConversationUseCase.invoke(viewModelScope, parametersOf(currentUser, conversation),
|
||||
deleteConversationUseCase.invoke(viewModelScope, parametersOf(
|
||||
currentUserLiveData.value,
|
||||
conversation
|
||||
),
|
||||
object : UseCaseResponse<GenericOverall> {
|
||||
override fun onSuccess(result: GenericOverall) {
|
||||
// TODO: Use binary search to find the right room
|
||||
conversations.find { it.conversationId == conversation.conversationId }
|
||||
?.let {
|
||||
conversations.remove(it)
|
||||
conversationsLiveListData.value = conversations
|
||||
if (conversations.isEmpty()) {
|
||||
viewState.value = LOADED_EMPTY
|
||||
}
|
||||
}
|
||||
override suspend fun onSuccess(result: GenericOverall) {
|
||||
offlineRepository.deleteConversation(
|
||||
currentUserLiveData.value!!.id, conversation
|
||||
.conversationId
|
||||
)
|
||||
}
|
||||
|
||||
override fun onError(errorModel: ErrorModel?) {
|
||||
messageData = errorModel?.getErrorMessage()
|
||||
viewModelScope.launch {
|
||||
setConversationUpdateStatus(conversation, false)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
@ -135,74 +141,63 @@ class ConversationsListViewModel constructor(
|
||||
conversation: Conversation,
|
||||
favorite: Boolean
|
||||
) {
|
||||
viewModelScope.launch {
|
||||
setConversationUpdateStatus(conversation, true)
|
||||
}
|
||||
|
||||
setConversationFavoriteValueUseCase.invoke(viewModelScope, parametersOf(
|
||||
currentUser,
|
||||
currentUserLiveData.value,
|
||||
conversation,
|
||||
favorite
|
||||
),
|
||||
object : UseCaseResponse<GenericOverall> {
|
||||
override fun onSuccess(result: GenericOverall) {
|
||||
// TODO: Use binary search to find the right room
|
||||
conversations.find { it.conversationId == conversation.conversationId }
|
||||
?.apply {
|
||||
updating = false
|
||||
isFavorite = favorite
|
||||
conversationsLiveListData.value = conversations
|
||||
}
|
||||
override suspend fun onSuccess(result: GenericOverall) {
|
||||
offlineRepository.setFavoriteValueForConversation(
|
||||
currentUserLiveData.value!!.id,
|
||||
conversation.conversationId, favorite
|
||||
)
|
||||
}
|
||||
|
||||
override fun onError(errorModel: ErrorModel?) {
|
||||
messageData = errorModel?.getErrorMessage()
|
||||
viewModelScope.launch {
|
||||
setConversationUpdateStatus(conversation, false)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun loadConversations() {
|
||||
val userChanged = !currentUser.equals(userUtils.currentUser)
|
||||
val userChanged = !(currentUserLiveData.value?.equals(userUtils.currentUser) ?: false)
|
||||
|
||||
if (userChanged) {
|
||||
currentUser = userUtils.currentUser
|
||||
}
|
||||
|
||||
if ((FAILED).equals(viewState.value) || (LOADED_EMPTY).equals(viewState.value) ||
|
||||
(INITIAL_LOAD).equals(viewState.value) || !currentUser.equals(userUtils.currentUser) || userChanged
|
||||
) {
|
||||
currentUserLiveData.value = userUtils.currentUser
|
||||
viewState.value = LOADING
|
||||
}
|
||||
|
||||
getConversationsUseCase.invoke(
|
||||
viewModelScope, parametersOf(currentUser), object : UseCaseResponse<List<Conversation>> {
|
||||
override fun onSuccess(result: List<Conversation>) {
|
||||
val newConversations = result.toMutableList()
|
||||
getConversationsUseCase.invoke(viewModelScope, parametersOf(currentUserLiveData.value), object :
|
||||
UseCaseResponse<List<Conversation>> {
|
||||
override suspend fun onSuccess(result: List<Conversation>) {
|
||||
val mutableList = result.toMutableList()
|
||||
mutableList.forEach {
|
||||
it.user = currentUserLiveData.value!!.id
|
||||
}
|
||||
|
||||
newConversations.sortWith(Comparator { conversation1, conversation2 ->
|
||||
CompareToBuilder()
|
||||
.append(conversation2.isFavorite, conversation1.isFavorite)
|
||||
.append(conversation2.lastActivity, conversation1.lastActivity)
|
||||
.toComparison()
|
||||
})
|
||||
|
||||
conversations = newConversations
|
||||
conversationsLiveListData.value = conversations
|
||||
viewState.value = if (newConversations.isNotEmpty()) LOADED else LOADED_EMPTY
|
||||
offlineRepository.saveConversationsForUser(currentUserLiveData.value!!, mutableList)
|
||||
messageData = ""
|
||||
}
|
||||
|
||||
override fun onError(errorModel: ErrorModel?) {
|
||||
messageData = errorModel?.getErrorMessage()
|
||||
viewState.value = FAILED
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
fun loadAvatar(avatarSize: Int) {
|
||||
val imageRequest = DisplayUtils.getImageRequestForUrl(
|
||||
ApiUtils.getUrlForAvatarWithNameAndPixels(
|
||||
currentUser.baseUrl,
|
||||
currentUser.userId, avatarSize
|
||||
currentUserLiveData.value!!.baseUrl,
|
||||
currentUserLiveData.value!!.userId, avatarSize
|
||||
), null
|
||||
)
|
||||
|
||||
@ -257,7 +252,7 @@ class ConversationsListViewModel constructor(
|
||||
fun getConversationMenuItemsForConversation(conversation: Conversation): MutableList<BasicListItemWithImage> {
|
||||
val items = mutableListOf<BasicListItemWithImage>()
|
||||
|
||||
if (conversation.isFavorite) {
|
||||
if (conversation.favorite) {
|
||||
items.add(
|
||||
BasicListItemWithImage(
|
||||
drawable.ic_star_border_black_24dp,
|
||||
@ -282,7 +277,7 @@ class ConversationsListViewModel constructor(
|
||||
)
|
||||
}
|
||||
|
||||
if (conversation.canLeave(currentUser)) {
|
||||
if (conversation.canLeave(currentUserLiveData.value!!)) {
|
||||
items.add(
|
||||
BasicListItemWithImage(
|
||||
drawable.ic_exit_to_app_black_24dp, context.getString
|
||||
@ -291,7 +286,7 @@ class ConversationsListViewModel constructor(
|
||||
)
|
||||
}
|
||||
|
||||
if (conversation.canModerate(currentUser)) {
|
||||
if (conversation.canModerate(currentUserLiveData.value!!)) {
|
||||
items.add(
|
||||
BasicListItemWithImage(
|
||||
drawable.ic_delete_grey600_24dp, context.getString(
|
||||
@ -304,14 +299,13 @@ class ConversationsListViewModel constructor(
|
||||
return items
|
||||
}
|
||||
|
||||
private fun setConversationUpdateStatus(
|
||||
private suspend fun setConversationUpdateStatus(
|
||||
conversation: Conversation,
|
||||
value: Boolean
|
||||
) {
|
||||
conversations.find { it.conversationId == conversation.conversationId }
|
||||
?.apply {
|
||||
updating = value
|
||||
conversationsLiveListData.value = conversations
|
||||
}
|
||||
offlineRepository.setChangingValueForConversation(
|
||||
currentUserLiveData.value!!.id, conversation
|
||||
.conversationId, value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ package com.nextcloud.talk.newarch.features.conversationsList.di.module
|
||||
|
||||
import android.app.Application
|
||||
import com.nextcloud.talk.newarch.data.source.remote.ApiErrorHandler
|
||||
import com.nextcloud.talk.newarch.domain.repository.NextcloudTalkOfflineRepository
|
||||
import com.nextcloud.talk.newarch.domain.repository.NextcloudTalkRepository
|
||||
import com.nextcloud.talk.newarch.domain.usecases.DeleteConversationUseCase
|
||||
import com.nextcloud.talk.newarch.domain.usecases.GetConversationsUseCase
|
||||
@ -41,7 +42,7 @@ val ConversationsListModule = module {
|
||||
factory {
|
||||
createConversationListViewModelFactory(
|
||||
androidApplication(), get(), get(), get(), get
|
||||
(), get()
|
||||
(), get(), get()
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -81,11 +82,12 @@ fun createConversationListViewModelFactory(
|
||||
setConversationFavoriteValueUseCase: SetConversationFavoriteValueUseCase,
|
||||
leaveConversationUseCase: LeaveConversationUseCase,
|
||||
deleteConversationUseCase: DeleteConversationUseCase,
|
||||
userUtils: UserUtils
|
||||
userUtils: UserUtils,
|
||||
offlineRepository: NextcloudTalkOfflineRepository
|
||||
): ConversationListViewModelFactory {
|
||||
return ConversationListViewModelFactory(
|
||||
application, getConversationsUseCase,
|
||||
setConversationFavoriteValueUseCase, leaveConversationUseCase, deleteConversationUseCase,
|
||||
userUtils
|
||||
userUtils, offlineRepository
|
||||
)
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.local.converters
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.bluelinelabs.logansquare.LoganSquare
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
|
||||
class ChatMessageConverter {
|
||||
@TypeConverter
|
||||
fun fromChatMessageToString(chatMessage: ChatMessage?): String {
|
||||
if (chatMessage == null) {
|
||||
return ""
|
||||
} else {
|
||||
return LoganSquare.serialize(chatMessage)
|
||||
}
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromStringToChatMessage(value: String): ChatMessage? {
|
||||
return LoganSquare.parse(value, ChatMessage::class.java)
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.local.converters
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationReadOnlyState
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationReadOnlyState.CONVERSATION_READ_ONLY
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationReadOnlyState.CONVERSATION_READ_WRITE
|
||||
|
||||
class ConversationReadOnlyStateConverter {
|
||||
@TypeConverter
|
||||
fun fromConversationReadOnlyStateToInt(conversationReadOnlyState: ConversationReadOnlyState):
|
||||
Int {
|
||||
return conversationReadOnlyState.ordinal
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromIntToConversationType(value: Int): ConversationReadOnlyState {
|
||||
when (value) {
|
||||
0 -> return CONVERSATION_READ_WRITE
|
||||
else -> return CONVERSATION_READ_ONLY
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.local.converters
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType.GROUP_CONVERSATION
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType.ONE_TO_ONE_CONVERSATION
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType.PUBLIC_CONVERSATION
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType.SYSTEM_CONVERSATION
|
||||
|
||||
class ConversationTypeConverter {
|
||||
@TypeConverter
|
||||
fun fromConversationTypeToInt(conversationType: ConversationType): Int {
|
||||
return conversationType.value
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromIntToConversationType(value: Int): ConversationType {
|
||||
when (value) {
|
||||
1 -> return ONE_TO_ONE_CONVERSATION
|
||||
2 -> return GROUP_CONVERSATION
|
||||
3 -> return PUBLIC_CONVERSATION
|
||||
else -> return SYSTEM_CONVERSATION
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.local.converters
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.LobbyState
|
||||
|
||||
class LobbyStateConverter {
|
||||
@TypeConverter
|
||||
fun fromLobbyStateToInt(lobbyState: LobbyState): Int {
|
||||
return lobbyState.ordinal
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromIntToLobbyState(value: Int): LobbyState {
|
||||
when (value) {
|
||||
0 -> return LobbyState.LOBBY_STATE_ALL_PARTICIPANTS
|
||||
else -> return LobbyState.LOBBY_STATE_ALL_PARTICIPANTS
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.local.converters
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.NotificationLevel
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.NotificationLevel.ALWAYS
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.NotificationLevel.DEFAULT
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.NotificationLevel.MENTION
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.NotificationLevel.NEVER
|
||||
|
||||
class NotificationLevelConverter {
|
||||
@TypeConverter
|
||||
fun fromNotificationLevelToInt(notificationLevel: NotificationLevel): Int {
|
||||
return notificationLevel.ordinal
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromIntToNotificationLevel(value: Int): NotificationLevel {
|
||||
when (value) {
|
||||
0 -> return DEFAULT
|
||||
1 -> return ALWAYS
|
||||
2 -> return MENTION
|
||||
else -> return NEVER
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.local.converters
|
||||
|
||||
import androidx.room.TypeConverter
|
||||
import com.nextcloud.talk.models.json.participants.Participant.ParticipantType
|
||||
import com.nextcloud.talk.models.json.participants.Participant.ParticipantType.DUMMY
|
||||
import com.nextcloud.talk.models.json.participants.Participant.ParticipantType.GUEST
|
||||
import com.nextcloud.talk.models.json.participants.Participant.ParticipantType.MODERATOR
|
||||
import com.nextcloud.talk.models.json.participants.Participant.ParticipantType.OWNER
|
||||
import com.nextcloud.talk.models.json.participants.Participant.ParticipantType.USER
|
||||
import com.nextcloud.talk.models.json.participants.Participant.ParticipantType.USER_FOLLOWING_LINK
|
||||
|
||||
class ParticipantTypeConverter {
|
||||
@TypeConverter
|
||||
fun fromParticipantType(participantType: ParticipantType): Int {
|
||||
return participantType.ordinal
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromIntToParticipantType(value: Int): ParticipantType {
|
||||
when (value) {
|
||||
0 -> return DUMMY
|
||||
1 -> return OWNER
|
||||
2 -> return MODERATOR
|
||||
3 -> return USER
|
||||
4 -> return GUEST
|
||||
else -> return USER_FOLLOWING_LINK
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.local.dao
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Delete
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room.Transaction
|
||||
import com.nextcloud.talk.newarch.local.models.ConversationEntity
|
||||
|
||||
@Dao
|
||||
abstract class ConversationsDao {
|
||||
@Query("SELECT * FROM conversations WHERE user = :userId")
|
||||
abstract fun getConversationsForUser(userId: Long): LiveData<List<ConversationEntity>>
|
||||
|
||||
@Query("DELETE FROM conversations WHERE user = :userId")
|
||||
abstract suspend fun clearConversationsForUser(userId: Long)
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
abstract suspend fun saveConversation(conversation: ConversationEntity)
|
||||
|
||||
suspend fun saveConversationWithTimestamp(conversation: ConversationEntity) {
|
||||
saveConversation(conversation.apply {
|
||||
modifiedAt = System.currentTimeMillis()
|
||||
})
|
||||
}
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
abstract suspend fun saveConversations(vararg conversations: ConversationEntity)
|
||||
|
||||
@Query(
|
||||
"UPDATE conversations SET changing = :changing WHERE user = :userId AND " +
|
||||
"'conversation_id' = :conversationId"
|
||||
)
|
||||
abstract suspend fun updateChangingValueForConversation(
|
||||
userId: Long,
|
||||
conversationId: String,
|
||||
changing: Boolean
|
||||
)
|
||||
|
||||
@Query(
|
||||
"UPDATE conversations SET favorite = :favorite, changing = 0 WHERE user = :userId AND 'conversation_id' = :conversationId"
|
||||
)
|
||||
abstract suspend fun updateFavoriteValueForConversation(
|
||||
userId: Long,
|
||||
conversationId: String,
|
||||
favorite: Boolean
|
||||
)
|
||||
|
||||
@Query("DELETE FROM conversations WHERE user = :userId AND 'conversation_id' = :conversationId")
|
||||
abstract suspend fun deleteConversation(
|
||||
userId: Long,
|
||||
conversationId: String
|
||||
)
|
||||
|
||||
@Delete
|
||||
abstract suspend fun deleteConversations(vararg conversation: ConversationEntity)
|
||||
|
||||
@Query("DELETE FROM conversations WHERE user = :userId AND 'modified_at' < :timestamp")
|
||||
abstract suspend fun deleteConversationsForUserWithTimestamp(
|
||||
userId: Long,
|
||||
timestamp: Long
|
||||
)
|
||||
|
||||
@Transaction
|
||||
open suspend fun updateConversationsForUser(
|
||||
userId: Long,
|
||||
newConversations:
|
||||
Array<ConversationEntity>
|
||||
) {
|
||||
val timestamp = System.currentTimeMillis()
|
||||
|
||||
val conversationsWithTimestampApplied = newConversations.map {
|
||||
it.modifiedAt = System.currentTimeMillis()
|
||||
it
|
||||
}
|
||||
.toTypedArray()
|
||||
|
||||
saveConversations(*conversationsWithTimestampApplied)
|
||||
deleteConversationsForUserWithTimestamp(userId, timestamp)
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.local.db
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.TypeConverters
|
||||
import com.nextcloud.talk.newarch.local.converters.ChatMessageConverter
|
||||
import com.nextcloud.talk.newarch.local.converters.ConversationReadOnlyStateConverter
|
||||
import com.nextcloud.talk.newarch.local.converters.ConversationTypeConverter
|
||||
import com.nextcloud.talk.newarch.local.converters.LobbyStateConverter
|
||||
import com.nextcloud.talk.newarch.local.converters.NotificationLevelConverter
|
||||
import com.nextcloud.talk.newarch.local.converters.ParticipantTypeConverter
|
||||
import com.nextcloud.talk.newarch.local.dao.ConversationsDao
|
||||
import com.nextcloud.talk.newarch.local.models.ConversationEntity
|
||||
|
||||
@Database(entities = arrayOf(ConversationEntity::class), version = 1)
|
||||
@TypeConverters(
|
||||
ChatMessageConverter::class, LobbyStateConverter::class,
|
||||
ConversationReadOnlyStateConverter::class, NotificationLevelConverter::class,
|
||||
ConversationTypeConverter::class, ParticipantTypeConverter::class
|
||||
)
|
||||
|
||||
abstract class TalkDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun conversationsDao(): ConversationsDao
|
||||
|
||||
companion object {
|
||||
private const val DB_NAME = "talk.db"
|
||||
@Volatile
|
||||
private var INSTANCE: TalkDatabase? = null
|
||||
|
||||
fun getInstance(context: Context): TalkDatabase =
|
||||
INSTANCE ?: synchronized(this) {
|
||||
INSTANCE ?: build(context).also { INSTANCE = it }
|
||||
}
|
||||
|
||||
private fun build(context: Context) =
|
||||
Room.databaseBuilder(context.applicationContext, TalkDatabase::class.java, DB_NAME)
|
||||
.build()
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.local.models
|
||||
|
||||
import androidx.annotation.NonNull
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationReadOnlyState
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.LobbyState
|
||||
import com.nextcloud.talk.models.json.conversations.Conversation.NotificationLevel
|
||||
import com.nextcloud.talk.models.json.participants.Participant
|
||||
import java.util.HashMap
|
||||
|
||||
@Entity(tableName = "conversations", primaryKeys = ["user", "conversation_id"])
|
||||
data class ConversationEntity(
|
||||
@NonNull @ColumnInfo(name = "user") var userId: Long,
|
||||
@NonNull @ColumnInfo(name = "conversation_id") var conversationId: String,
|
||||
@ColumnInfo(name = "token") var token: String? = null,
|
||||
@ColumnInfo(name = "name") var name: String? = null,
|
||||
@ColumnInfo(name = "display_name") var displayName: String? = null,
|
||||
@ColumnInfo(name = "type") var type: ConversationType? = null,
|
||||
@ColumnInfo(name = "count") var count: Long = 0,
|
||||
@ColumnInfo(name = "number_of_guests") var numberOfGuests: Long = 0,
|
||||
/*@ColumnInfo(name = "guest_list") var guestList: HashMap<String, HashMap<String, Any>>? = null,
|
||||
@ColumnInfo(name = "participants") var participants: HashMap<String, HashMap<String, Any>>? =
|
||||
null,
|
||||
*/
|
||||
// hack for participants list
|
||||
@ColumnInfo(name = "participants_count") var participantsCount: Int = 0,
|
||||
@ColumnInfo(name = "participant_type") var participantType: Participant.ParticipantType? = null,
|
||||
@ColumnInfo(name = "has_password") var hasPassword: Boolean = false,
|
||||
@ColumnInfo(name = "session_id") var sessionId: String? = null,
|
||||
@ColumnInfo(name = "favorite") var favorite: Boolean = false,
|
||||
@ColumnInfo(name = "last_activity") var lastActivity: Long = 0,
|
||||
@ColumnInfo(name = "unread_messages") var unreadMessages: Int = 0,
|
||||
@ColumnInfo(name = "unread_mention") var unreadMention: Boolean = false,
|
||||
@ColumnInfo(name = "last_message") var lastMessage: ChatMessage? = null,
|
||||
@ColumnInfo(name = "object_type") var objectType: String? = null,
|
||||
@ColumnInfo(name = "notification_level") var notificationLevel: NotificationLevel? = null,
|
||||
@ColumnInfo(
|
||||
name = "read_only_state"
|
||||
) var conversationReadOnlyState: ConversationReadOnlyState? = null,
|
||||
@ColumnInfo(name = "lobby_state") var lobbyState: LobbyState? = null,
|
||||
@ColumnInfo(name = "lobby_timer") var lobbyTimer: Long? = null,
|
||||
@ColumnInfo(name = "last_read_message_id") var lastReadMessageId: Int = 0,
|
||||
@ColumnInfo(name = "modified_at") var modifiedAt: Long? = null,
|
||||
@ColumnInfo(name = "changing") var changing: Boolean = false
|
||||
)
|
||||
|
||||
fun ConversationEntity.toConversation(): Conversation {
|
||||
val conversation = Conversation()
|
||||
conversation.user = this.userId
|
||||
conversation.conversationId = this.conversationId
|
||||
conversation.type = this.type
|
||||
conversation.token = this.token
|
||||
conversation.name = this.name
|
||||
conversation.displayName = this.displayName
|
||||
conversation.count = this.count
|
||||
conversation.numberOfGuests = this.numberOfGuests
|
||||
conversation.participants = HashMap()
|
||||
for (i in 0 until participantsCount) {
|
||||
conversation.participants?.put(i.toString(), HashMap())
|
||||
}
|
||||
conversation.participantType = this.participantType
|
||||
conversation.hasPassword = this.hasPassword
|
||||
conversation.sessionId = this.sessionId
|
||||
conversation.favorite = this.favorite
|
||||
conversation.lastActivity = this.lastActivity
|
||||
conversation.unreadMessages = this.unreadMessages
|
||||
conversation.unreadMention = this.unreadMention
|
||||
conversation.lastMessage = this.lastMessage
|
||||
conversation.objectType = this.objectType
|
||||
conversation.notificationLevel = this.notificationLevel
|
||||
conversation.conversationReadOnlyState = this.conversationReadOnlyState
|
||||
conversation.lobbyState = this.lobbyState
|
||||
conversation.lobbyTimer = this.lobbyTimer
|
||||
conversation.lastReadMessageId = this.lastReadMessageId
|
||||
conversation.changing = this.changing
|
||||
|
||||
return conversation
|
||||
}
|
||||
|
||||
fun Conversation.toConversationEntity(): ConversationEntity {
|
||||
val conversationEntity = ConversationEntity(this.user, this.conversationId)
|
||||
conversationEntity.token = this.token
|
||||
conversationEntity.name = this.name
|
||||
conversationEntity.displayName = this.displayName
|
||||
conversationEntity.count = this.count
|
||||
conversationEntity.numberOfGuests = this.numberOfGuests
|
||||
conversationEntity.participantsCount = this.participants?.size ?: 0
|
||||
conversationEntity.participantType = this.participantType
|
||||
conversationEntity.hasPassword = this.hasPassword
|
||||
conversationEntity.sessionId = this.sessionId
|
||||
conversationEntity.favorite = this.favorite
|
||||
conversationEntity.lastActivity = this.lastActivity
|
||||
conversationEntity.unreadMessages = this.unreadMessages
|
||||
conversationEntity.unreadMention = this.unreadMention
|
||||
conversationEntity.lastMessage = this.lastMessage
|
||||
conversationEntity.objectType = this.objectType
|
||||
conversationEntity.notificationLevel = this.notificationLevel
|
||||
conversationEntity.conversationReadOnlyState = this.conversationReadOnlyState
|
||||
conversationEntity.lobbyState = this.lobbyState
|
||||
conversationEntity.lobbyTimer = this.lobbyTimer
|
||||
conversationEntity.lastReadMessageId = this.lastReadMessageId
|
||||
conversationEntity.type = this.type
|
||||
conversationEntity.changing = this.changing
|
||||
|
||||
return conversationEntity
|
||||
}
|
@ -83,7 +83,8 @@ class NetworkUtils {
|
||||
return null
|
||||
}
|
||||
}
|
||||
return response.request().newBuilder()
|
||||
return response.request()
|
||||
.newBuilder()
|
||||
.header(authenticatorType, credentials)
|
||||
.build()
|
||||
}
|
||||
|
@ -21,7 +21,6 @@
|
||||
package com.nextcloud.talk.newarch.utils
|
||||
|
||||
enum class ViewState {
|
||||
INITIAL_LOAD,
|
||||
LOADING,
|
||||
LOADED_EMPTY,
|
||||
LOADED,
|
||||
|
@ -24,28 +24,36 @@
|
||||
android:id="@+id/generic_rv_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true">
|
||||
android:animateLayoutChanges="true"
|
||||
>
|
||||
|
||||
<include layout="@layout/view_states"/>
|
||||
<include
|
||||
layout="@layout/view_states"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
/>
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefreshLayoutView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="visible"
|
||||
app:layout_behavior="com.nextcloud.talk.utils.FABAwareScrollingViewBehavior">
|
||||
app:layout_behavior="com.nextcloud.talk.utils.FABAwareScrollingViewBehavior"
|
||||
>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/dataStateView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/dataStateView"
|
||||
android:visibility="invisible">
|
||||
android:visibility="invisible"
|
||||
>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/rv_item_conversation" />
|
||||
tools:listitem="@layout/rv_item_conversation"
|
||||
/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
@ -58,7 +66,8 @@
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="16dp"
|
||||
android:visibility="gone"
|
||||
app:srcCompat="@drawable/ic_add_white_24px" />
|
||||
app:srcCompat="@drawable/ic_add_white_24px"
|
||||
/>
|
||||
|
||||
<include layout="@layout/fast_scroller" />
|
||||
|
||||
|
@ -88,7 +88,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Select an account</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Start a conversation</string>
|
||||
<string name="nc_configure_room">Configure conversation</string>
|
||||
<string name="nc_leave">Leave conversation</string>
|
||||
|
@ -124,7 +124,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Selecciona un compte</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Enceta una conversa</string>
|
||||
<string name="nc_configure_room">Configura la conversa</string>
|
||||
<string name="nc_leave">Surt de la conversa</string>
|
||||
|
@ -124,7 +124,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Vyberte účet</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Začněte konverzaci</string>
|
||||
<string name="nc_configure_room">Nastavení konverzace</string>
|
||||
<string name="nc_leave">Opustit konverzaci</string>
|
||||
|
@ -124,7 +124,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Vælg konto</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Start en samtale</string>
|
||||
<string name="nc_configure_room">Samtaleopsætning</string>
|
||||
<string name="nc_leave">Forlad samtale</string>
|
||||
|
@ -125,7 +125,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Konto auswählen</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Starte eine Unterhaltung</string>
|
||||
<string name="nc_configure_room">Unterhaltung einrichten</string>
|
||||
<string name="nc_leave">Unterhaltung verlassen</string>
|
||||
|
@ -93,7 +93,7 @@
|
||||
<string name="nc_license_title">Άδεια χρήσης</string>
|
||||
<string name="nc_select_an_account">Επιλογή λογαριασμού</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Έναρξη συνομιλίας</string>
|
||||
<string name="nc_configure_room">Ρύθμιση συνομιλίας</string>
|
||||
<string name="nc_leave">Εγκατάλειψη συνομιλίας</string>
|
||||
|
@ -124,7 +124,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Selecciona una cuenta</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Comienza una conversación</string>
|
||||
<string name="nc_configure_room">Configura la conversación</string>
|
||||
<string name="nc_leave">Abandonar conversación</string>
|
||||
|
@ -124,7 +124,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Choisissez un compte</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Commencer une conversation</string>
|
||||
<string name="nc_configure_room">Configurer la conversation</string>
|
||||
<string name="nc_leave">Quitter la conversation</string>
|
||||
|
@ -127,7 +127,7 @@ Produciuse un fallo aorecuperar os axustes da sinalización</string>
|
||||
|
||||
<string name="nc_select_an_account">Seleccione unha conta</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Iniciar unha conversa</string>
|
||||
<string name="nc_configure_room">Configurar a conversa</string>
|
||||
<string name="nc_leave">Abandonar a conversa</string>
|
||||
|
@ -123,7 +123,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Odaberi račun</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Započni razgovor</string>
|
||||
<string name="nc_configure_room">Konfiguriraj razgovor</string>
|
||||
<string name="nc_leave">Napusti razgovor</string>
|
||||
|
@ -123,7 +123,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Válasszon fiókot</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Beszélgetés indítása</string>
|
||||
<string name="nc_configure_room">Beszélgetés beállításai</string>
|
||||
<string name="nc_leave">Beszélgetés elhagyása</string>
|
||||
|
@ -110,7 +110,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Veldu aðgang</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Hefja samtal</string>
|
||||
<string name="nc_configure_room">Stilla samtal</string>
|
||||
<string name="nc_leave">Hætta í samtali</string>
|
||||
|
@ -125,7 +125,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Seleziona account</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Inizia una conversazione</string>
|
||||
<string name="nc_configure_room">Configura conversazione</string>
|
||||
<string name="nc_leave">Lascia la conversazione</string>
|
||||
|
@ -103,7 +103,7 @@
|
||||
|
||||
<string name="nc_select_an_account">בחירת חשבון</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">התחלת דיון</string>
|
||||
<string name="nc_configure_room">הגדרת דיון</string>
|
||||
<string name="nc_leave">יציאה מהדיון</string>
|
||||
|
@ -124,7 +124,7 @@
|
||||
|
||||
<string name="nc_select_an_account">アカウントを選択</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">会話を開始する</string>
|
||||
<string name="nc_configure_room">会話を構成する</string>
|
||||
<string name="nc_leave">会話を離れる</string>
|
||||
|
@ -104,7 +104,7 @@
|
||||
|
||||
<string name="nc_select_an_account">계정 선택</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">대화 시작</string>
|
||||
<string name="nc_configure_room">대화 설정</string>
|
||||
<string name="nc_leave">대화 나가기</string>
|
||||
|
@ -93,7 +93,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Velg en konto</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Start en samtale</string>
|
||||
<string name="nc_configure_room">Konfigurer samtale</string>
|
||||
<string name="nc_leave">Forlat samtale</string>
|
||||
|
@ -126,7 +126,7 @@ Kies er eentje van een provider.</string>
|
||||
|
||||
<string name="nc_select_an_account">Selecteer een account</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Begin een gesprek</string>
|
||||
<string name="nc_configure_room">Configureren gesprek</string>
|
||||
<string name="nc_leave">Verlaat gesprek</string>
|
||||
|
@ -125,7 +125,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Wybierz konto</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Rozpocznij rozmowę</string>
|
||||
<string name="nc_configure_room">Konfiguruj rozmowę</string>
|
||||
<string name="nc_leave">Opuść rozmowę</string>
|
||||
|
@ -125,7 +125,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Selecionar uma conta</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Iniciar uma conversa</string>
|
||||
<string name="nc_configure_room">Configurar uma conversa</string>
|
||||
<string name="nc_leave">Sair da conversa</string>
|
||||
|
@ -95,7 +95,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Selecionar uma conta</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Iniciar uma conversação</string>
|
||||
<string name="nc_configure_room">Configurar conversação</string>
|
||||
<string name="nc_leave">Sair da conversação</string>
|
||||
|
@ -124,7 +124,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Выберите учётную запись</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Начать беседу</string>
|
||||
<string name="nc_configure_room">Настроить беседу</string>
|
||||
<string name="nc_leave">Покинуть беседу</string>
|
||||
|
@ -123,7 +123,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Zvoľte si účet</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Začať rozhovor</string>
|
||||
<string name="nc_configure_room">Nastavenia rozhovoru</string>
|
||||
<string name="nc_leave">Odísť z rozhovoru</string>
|
||||
|
@ -115,7 +115,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Izbor računa</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Začni s pogovorom</string>
|
||||
<string name="nc_configure_room">Nastavitev pogovora</string>
|
||||
<string name="nc_leave">Zapusti pogovor</string>
|
||||
|
@ -124,7 +124,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Изаберите налог</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Започни разговор</string>
|
||||
<string name="nc_configure_room">Подеси разговор</string>
|
||||
<string name="nc_leave">Напусти разговор</string>
|
||||
|
@ -125,7 +125,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Välj ett konto</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Starta en konversation</string>
|
||||
<string name="nc_configure_room">Anpassa konversation</string>
|
||||
<string name="nc_leave">Lämna konversationen</string>
|
||||
|
@ -125,7 +125,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Bir hesap seçin</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Yeni bir görüşme başlat</string>
|
||||
<string name="nc_configure_room">Görüşmeyi yapılandır</string>
|
||||
<string name="nc_leave">Görüşmeden ayrıl</string>
|
||||
|
@ -83,7 +83,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Chọn một tài khoản</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Bắt đầu một cuộc Đàm thoại</string>
|
||||
<string name="nc_configure_room">Cấu hình đàm thoại</string>
|
||||
<string name="nc_leave">Rời khỏi cuộc đàm thoại</string>
|
||||
|
@ -124,7 +124,7 @@
|
||||
|
||||
<string name="nc_select_an_account">选择一个账户</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">发起会话</string>
|
||||
<string name="nc_configure_room">配置会话</string>
|
||||
<string name="nc_leave">离开会话</string>
|
||||
|
@ -99,7 +99,7 @@
|
||||
|
||||
<string name="nc_select_an_account">選擇一個帳號</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">新對話</string>
|
||||
<string name="nc_configure_room">設定對話</string>
|
||||
<string name="nc_leave">結束對話</string>
|
||||
|
@ -144,7 +144,7 @@
|
||||
|
||||
<string name="nc_select_an_account">Select an account</string>
|
||||
|
||||
<!-- Conversation menu -->
|
||||
<!-- ConversationEntity menu -->
|
||||
<string name="nc_start_conversation">Start a conversation</string>
|
||||
<string name="nc_configure_room">Configure conversation</string>
|
||||
<string name="nc_leave">Leave conversation</string>
|
||||
|
Loading…
Reference in New Issue
Block a user