Fix issue with storing participants list

This commit is contained in:
Mario Danic 2019-12-29 01:25:33 +01:00 committed by Mario Đanić
parent f1ffff49e5
commit 72251d1e58
11 changed files with 148 additions and 63 deletions

View File

@ -23,6 +23,7 @@ apply plugin: 'findbugs'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlinx-serialization'
def taskRequest = getGradle().getStartParameter().getTaskRequests().toString()
if (taskRequest.contains("Gplay") || taskRequest.contains("findbugs") ||
@ -160,7 +161,7 @@ ext {
koin_version = "2.1.0-alpha-1"
lifecycle_version = "2.2.0-rc01"
coil_version = "0.8.0"
room_version = "2.2.2"
room_version = "2.2.3"
}
configurations.all {
@ -173,6 +174,7 @@ dependencies {
implementation fileTree(include: ['*'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.14.0" // JVM dependency
// Koin for Android
implementation "org.koin:koin-android:$koin_version"
// Koin AndroidX Scope features
@ -227,8 +229,8 @@ dependencies {
androidTestImplementation "androidx.work:work-testing:$work_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.2.0-alpha02'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta3'
implementation 'com.google.android.material:material:1.2.0-alpha03'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
implementation 'com.github.vanniktech:Emoji:0.6.0'
implementation group: 'androidx.emoji', name: 'emoji-bundled', version: '1.0.0'
implementation 'org.michaelevans.colorart:library:0.0.3'

View File

@ -2,11 +2,11 @@
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "3a9126341dd46ffc54056126b59ed5fb",
"identityHash": "2c4f372b48cd11e679b04c6d577f1cd8",
"entities": [
{
"tableName": "conversations",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `user_id` INTEGER, `conversation_id` TEXT, `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` INTEGER NOT NULL, `can_start_call` INTEGER, `modified_at` INTEGER, `changing` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`user_id`) REFERENCES `users`(`id`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `user_id` INTEGER, `conversation_id` TEXT, `token` TEXT, `name` TEXT, `display_name` TEXT, `type` INTEGER, `count` INTEGER NOT NULL, `number_of_guests` INTEGER NOT NULL, `participants` TEXT, `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` INTEGER NOT NULL, `can_start_call` INTEGER, `modified_at` INTEGER, `changing` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`user_id`) REFERENCES `users`(`id`) ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)",
"fields": [
{
"fieldPath": "id",
@ -63,10 +63,10 @@
"notNull": true
},
{
"fieldPath": "participantsCount",
"columnName": "participants_count",
"affinity": "INTEGER",
"notNull": true
"fieldPath": "participants",
"columnName": "participants",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "participantType",
@ -389,7 +389,7 @@
"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, '3a9126341dd46ffc54056126b59ed5fb')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '2c4f372b48cd11e679b04c6d577f1cd8')"
]
}
}

View File

@ -61,7 +61,7 @@ class Conversation {
/*@JsonField(name = ["guestList"])
var guestList: HashMap<String, HashMap<String, Any>>? = null*/
@JsonField(name = ["participants"])
var participants: HashMap<String, HashMap<String, Any>>? = null
var participants: HashMap<String, Participant>? = null
@JsonField(name = ["participantType"], typeConverter = EnumParticipantTypeConverter::class)
var participantType: Participant.ParticipantType? = null
@JsonField(name = ["hasPassword"])

View File

@ -0,0 +1,36 @@
/*
*
* * Nextcloud Talk application
* *
* * @author Mario Danic
* * Copyright (C) 2017-2020 Mario Danic <mario@lovelyhq.com>
* *
* * This program is free software: you can redistribute it and/or modify
* * it under the terms of the GNU General Public License as published by
* * the Free Software Foundation, either version 3 of the License, or
* * at your option) any later version.
* *
* * This program is distributed in the hope that it will be useful,
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* * GNU General Public License for more details.
* *
* * You should have received a copy of the GNU General Public License
* * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.nextcloud.talk.models.json.converters
import com.bluelinelabs.logansquare.typeconverters.LongBasedTypeConverter
import com.nextcloud.talk.models.json.participants.Participant
class EnumParticipantFlagsConverter : LongBasedTypeConverter<Participant.ParticipantFlags>() {
override fun getFromLong(l: Long): Participant.ParticipantFlags {
return Participant.ParticipantFlags.fromValue(l)
}
override fun convertToLong(`object`: Participant.ParticipantFlags?): Long {
return `object`?.value ?: 0
}
}

View File

@ -38,16 +38,16 @@ public class EnumParticipantTypeConverter
return Participant.ParticipantType.GUEST;
case 5:
return Participant.ParticipantType.USER_FOLLOWING_LINK;
case 6:
return Participant.ParticipantType.GUEST_AS_MODERATOR;
default:
return Participant.ParticipantType.DUMMY;
return Participant.ParticipantType.GUEST;
}
}
@Override
public int convertToInt(Participant.ParticipantType object) {
switch (object) {
case DUMMY:
return 0;
case OWNER:
return 1;
case MODERATOR:
@ -58,6 +58,8 @@ public class EnumParticipantTypeConverter
return 4;
case USER_FOLLOWING_LINK:
return 5;
case GUEST_AS_MODERATOR:
return 6;
default:
return 0;
}

View File

@ -22,11 +22,10 @@ package com.nextcloud.talk.models.json.participants;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import com.nextcloud.talk.models.json.converters.EnumParticipantFlagsConverter;
import com.nextcloud.talk.models.json.converters.EnumParticipantTypeConverter;
import com.nextcloud.talk.models.json.converters.ObjectParcelConverter;
import org.parceler.Parcel;
import org.parceler.ParcelPropertyConverter;
import lombok.Data;
@ -55,39 +54,52 @@ public class Participant {
public String sessionId;
@JsonField(name = "conversationId")
public long roomId;
public long conversationId;
@ParcelPropertyConverter(ObjectParcelConverter.class)
@JsonField(name = "inCall")
public Object inCall;
@JsonField(name = { "inCall", "call" }, typeConverter = EnumParticipantFlagsConverter.class)
public ParticipantFlags participantFlags;
@JsonField(name = "source")
public String source;
public boolean selected;
public enum ParticipantType {
OWNER(1),
MODERATOR(2),
USER(3),
GUEST(4),
USER_FOLLOWING_LINK(5),
GUEST_AS_MODERATOR(6);
public ParticipantFlags getParticipantFlags() {
ParticipantFlags participantFlags = ParticipantFlags.NOT_IN_CALL;
if (inCall != null) {
if (inCall instanceof Long) {
participantFlags = ParticipantFlags.fromValue((Long) inCall);
} else if (inCall instanceof Boolean) {
if ((boolean) inCall) {
participantFlags = ParticipantFlags.IN_CALL;
} else {
participantFlags = ParticipantFlags.NOT_IN_CALL;
}
private long value;
ParticipantType(long value) {
this.value = value;
}
public static ParticipantType fromValue(long value) {
if (value == 1) {
return OWNER;
} else if (value == 2) {
return MODERATOR;
} else if (value == 3) {
return USER;
} else if (value == 4) {
return GUEST;
} else if (value == 5) {
return USER_FOLLOWING_LINK;
} else if (value == 6) {
return GUEST_AS_MODERATOR;
} else {
return GUEST;
}
}
return participantFlags;
}
public long getValue() {
return value;
}
public enum ParticipantType {
DUMMY,
OWNER,
MODERATOR,
USER,
GUEST,
USER_FOLLOWING_LINK
}
public enum ParticipantFlags {

View File

@ -0,0 +1,48 @@
/*
*
* * Nextcloud Talk application
* *
* * @author Mario Danic
* * Copyright (C) 2017-2020 Mario Danic <mario@lovelyhq.com>
* *
* * This program is free software: you can redistribute it and/or modify
* * it under the terms of the GNU General Public License as published by
* * the Free Software Foundation, either version 3 of the License, or
* * at your option) any later version.
* *
* * This program is distributed in the hope that it will be useful,
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* * GNU General Public License for more details.
* *
* * You should have received a copy of the GNU General Public License
* * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.nextcloud.talk.newarch.local.converters
import androidx.room.TypeConverter
import com.bluelinelabs.logansquare.LoganSquare
import com.nextcloud.talk.models.json.participants.Participant
class ParticipantMapConverter {
@TypeConverter
fun fromMapToString(map: HashMap<String, Participant>?): String? {
if (map == null) {
return ""
}
return LoganSquare.serialize(map)
}
@TypeConverter
fun fromStringToHashMap(value: String?): HashMap<String, Participant>? {
if (value.isNullOrEmpty()) {
return null
}
return LoganSquare.parse(value, HashMap::class.java) as java.util.HashMap<String, Participant>?
}
}

View File

@ -22,7 +22,6 @@ 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.*
class ParticipantTypeConverter {
@TypeConverter
@ -32,14 +31,6 @@ class ParticipantTypeConverter {
@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
}
return ParticipantType.fromValue(value.toLong())
}
}

View File

@ -44,7 +44,7 @@ import com.nextcloud.talk.newarch.local.models.UserNgEntity
ConversationTypeConverter::class, ParticipantTypeConverter::class,
PushConfigurationConverter::class, CapabilitiesConverter::class,
ExternalSignalingConverter::class,
UserStatusConverter::class, SystemMessageTypeConverter::class
UserStatusConverter::class, SystemMessageTypeConverter::class, ParticipantMapConverter::class
)
abstract class TalkDatabase : RoomDatabase() {

View File

@ -25,6 +25,7 @@ import androidx.room.ForeignKey.CASCADE
import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.models.json.conversations.Conversation
import com.nextcloud.talk.models.json.conversations.Conversation.*
import com.nextcloud.talk.models.json.participants.Participant
import com.nextcloud.talk.models.json.participants.Participant.ParticipantType
import java.util.*
@ -50,12 +51,7 @@ data class ConversationEntity(
@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 = "participants") var participants: HashMap<String, Participant>? = null,
@ColumnInfo(name = "participant_type") var participantType: ParticipantType? = null,
@ColumnInfo(name = "has_password") var hasPassword: Boolean = false,
@ColumnInfo(name = "session_id") var sessionId: String? = null,
@ -92,7 +88,7 @@ data class ConversationEntity(
if (type != other.type) return false
if (count != other.count) return false
if (numberOfGuests != other.numberOfGuests) return false
if (participantsCount != other.participantsCount) return false
if (participants != other.participants) return false
if (participantType != other.participantType) return false
if (hasPassword != other.hasPassword) return false
if (sessionId != other.sessionId) return false
@ -130,10 +126,7 @@ fun ConversationEntity.toConversation(): Conversation {
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.participants = this.participants
conversation.participantType = this.participantType
conversation.hasPassword = this.hasPassword
conversation.sessionId = this.sessionId
@ -163,7 +156,7 @@ fun Conversation.toConversationEntity(): ConversationEntity {
conversationEntity.displayName = this.displayName
conversationEntity.count = this.count
conversationEntity.numberOfGuests = this.numberOfGuests
conversationEntity.participantsCount = this.participants?.size ?: 0
conversationEntity.participants = this.participants
conversationEntity.participantType = this.participantType
conversationEntity.hasPassword = this.hasPassword
conversationEntity.sessionId = this.sessionId

View File

@ -35,6 +35,7 @@ buildscript {
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files