Просмотр исходного кода

port room database layer from master-broken to up-to-date master

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
Andy Scherzinger 2 лет назад
Родитель
Сommit
db1dd66204
21 измененных файлов с 602 добавлено и 2 удалено
  1. 10 0
      app/build.gradle
  2. 74 0
      app/src/main/java/com/nextcloud/talk/data/source/local/TalkDatabase.kt
  3. 45 0
      app/src/main/java/com/nextcloud/talk/data/source/local/converters/CapabilitiesConverter.kt
  4. 44 0
      app/src/main/java/com/nextcloud/talk/data/source/local/converters/HashMapHashMapConverter.kt
  5. 34 0
      app/src/main/java/com/nextcloud/talk/data/source/local/converters/JsonConfiguration.kt
  6. 48 0
      app/src/main/java/com/nextcloud/talk/data/source/local/converters/PushConfigurationConverter.kt
  7. 48 0
      app/src/main/java/com/nextcloud/talk/data/source/local/converters/SignalingSettingsConverter.kt
  8. 118 0
      app/src/main/java/com/nextcloud/talk/data/user/UsersDao.kt
  9. 87 0
      app/src/main/java/com/nextcloud/talk/data/user/model/User.kt
  10. 73 0
      app/src/main/java/com/nextcloud/talk/data/user/model/UserNgEntity.kt
  11. 2 0
      app/src/main/java/com/nextcloud/talk/models/json/capabilities/Capabilities.kt
  12. 2 0
      app/src/main/java/com/nextcloud/talk/models/json/capabilities/NotificationsCapability.kt
  13. 2 0
      app/src/main/java/com/nextcloud/talk/models/json/capabilities/ProvisioningCapability.kt
  14. 2 0
      app/src/main/java/com/nextcloud/talk/models/json/capabilities/SpreedCapability.kt
  15. 2 0
      app/src/main/java/com/nextcloud/talk/models/json/capabilities/ThemingCapability.kt
  16. 2 0
      app/src/main/java/com/nextcloud/talk/models/json/capabilities/UserStatusCapability.kt
  17. 2 0
      app/src/main/java/com/nextcloud/talk/models/json/push/PushConfigurationState.kt
  18. 2 0
      app/src/main/java/com/nextcloud/talk/models/json/signaling/settings/IceServer.kt
  19. 3 1
      app/src/main/java/com/nextcloud/talk/models/json/signaling/settings/SignalingSettings.kt
  20. 1 1
      app/src/main/java/com/nextcloud/talk/models/json/signaling/settings/SignalingSettingsOcs.kt
  21. 1 0
      build.gradle

+ 10 - 0
app/build.gradle

@@ -33,6 +33,7 @@ apply plugin: 'kotlin-android-extensions'
 apply plugin: 'com.github.spotbugs'
 apply plugin: 'io.gitlab.arturbosch.detekt'
 apply plugin: "org.jlleitschuh.gradle.ktlint"
+apply plugin: 'kotlinx-serialization'
 
 android {
     compileSdkVersion 31
@@ -157,6 +158,7 @@ ext {
     materialDialogsVersion = "3.3.0"
     parcelerVersion = "1.1.13"
     retrofit2Version = "2.9.0"
+    roomVersion = "2.2.5"
     workVersion = "2.7.1"
     markwonVersion = "4.6.2"
     espressoVersion = "3.4.0"
@@ -179,6 +181,9 @@ dependencies {
     detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.20.0")
 	
     implementation fileTree(include: ['*'], dir: 'libs')
+
+    implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3"
+
     implementation 'androidx.appcompat:appcompat:1.4.2'
     implementation 'com.google.android.material:material:1.6.1'
     implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
@@ -236,6 +241,11 @@ dependencies {
     implementation 'io.requery:requery-android:1.6.1'
     implementation 'net.zetetic:android-database-sqlcipher:4.5.1'
     kapt 'io.requery:requery-processor:1.6.1'
+
+    implementation "androidx.room:room-runtime:${roomVersion}"
+    kapt "androidx.room:room-compiler:${roomVersion}" // For Kotlin use kapt instead of annotationProcessor
+    implementation "androidx.room:room-ktx:${roomVersion}"
+
     implementation "org.parceler:parceler-api:$parcelerVersion"
     implementation 'net.orange-box.storebox:storebox-lib:1.4.0'
     implementation "com.jakewharton:butterknife:${butterknifeVersion}"

+ 74 - 0
app/src/main/java/com/nextcloud/talk/data/source/local/TalkDatabase.kt

@@ -0,0 +1,74 @@
+/*
+ * 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.data.source.local
+
+import android.content.Context
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
+import androidx.room.TypeConverters
+import androidx.sqlite.db.SupportSQLiteDatabase
+import com.nextcloud.talk.data.source.local.converters.CapabilitiesConverter
+import com.nextcloud.talk.data.source.local.converters.HashMapHashMapConverter
+import com.nextcloud.talk.data.source.local.converters.PushConfigurationConverter
+import com.nextcloud.talk.data.source.local.converters.SignalingSettingsConverter
+import com.nextcloud.talk.data.user.UsersDao
+import com.nextcloud.talk.data.user.model.UserNgEntity
+
+@Database(
+    entities = [UserNgEntity::class],
+    version = 1,
+    exportSchema = true
+)
+@TypeConverters(
+    PushConfigurationConverter::class,
+    CapabilitiesConverter::class,
+    SignalingSettingsConverter::class,
+    HashMapHashMapConverter::class
+)
+
+abstract class TalkDatabase : RoomDatabase() {
+
+    abstract fun usersDao(): UsersDao
+
+    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)
+                .fallbackToDestructiveMigration()
+                .addCallback(object : RoomDatabase.Callback() {
+                    override fun onOpen(db: SupportSQLiteDatabase) {
+                        super.onOpen(db)
+                        db.execSQL("PRAGMA defer_foreign_keys = 1")
+                    }
+                })
+                .build()
+    }
+}

+ 45 - 0
app/src/main/java/com/nextcloud/talk/data/source/local/converters/CapabilitiesConverter.kt

@@ -0,0 +1,45 @@
+/*
+ * 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.data.source.local.converters
+
+import androidx.room.TypeConverter
+import com.bluelinelabs.logansquare.LoganSquare
+import com.nextcloud.talk.models.json.capabilities.Capabilities
+
+class CapabilitiesConverter {
+    @TypeConverter
+    fun fromCapabilitiesToString(capabilities: Capabilities?): String {
+        return if (capabilities == null) {
+            ""
+        } else {
+            LoganSquare.serialize(capabilities)
+        }
+    }
+
+    @TypeConverter
+    fun fromStringToCapabilities(value: String): Capabilities? {
+        if (value.isBlank()) {
+            return null
+        }
+
+        return LoganSquare.parse(value, Capabilities::class.java)
+    }
+}

+ 44 - 0
app/src/main/java/com/nextcloud/talk/data/source/local/converters/HashMapHashMapConverter.kt

@@ -0,0 +1,44 @@
+/*
+ * 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.data.source.local.converters
+
+import androidx.room.TypeConverter
+import com.bluelinelabs.logansquare.LoganSquare
+
+class HashMapHashMapConverter {
+    @TypeConverter
+    fun fromDoubleHashMapToString(map: HashMap<String, HashMap<String, String>>?): String? {
+        return if (map == null) {
+            LoganSquare.serialize(hashMapOf<String, HashMap<String, String>>())
+        } else {
+            return LoganSquare.serialize(map)
+        }
+    }
+
+    @TypeConverter
+    fun fromStringToDoubleHashMap(value: String?): HashMap<String, HashMap<String, String>>? {
+        if (value.isNullOrEmpty()) {
+            return hashMapOf()
+        }
+
+        return LoganSquare.parseMap(value, HashMap::class.java) as HashMap<String, HashMap<String, String>>?
+    }
+}

+ 34 - 0
app/src/main/java/com/nextcloud/talk/data/source/local/converters/JsonConfiguration.kt

@@ -0,0 +1,34 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Andy Scherzinger
+ * @author Mario Danic
+ * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
+ * 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.data.source.local.converters
+
+import kotlinx.serialization.json.Json
+
+sealed class JsonConfiguration {
+    companion object {
+        val customJsonConfiguration = Json {
+            prettyPrint = true;
+            useArrayPolymorphism = true
+        }
+    }
+}

+ 48 - 0
app/src/main/java/com/nextcloud/talk/data/source/local/converters/PushConfigurationConverter.kt

@@ -0,0 +1,48 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Andy Scherzinger
+ * @author Mario Danic
+ * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
+ * 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.data.source.local.converters
+
+import androidx.room.TypeConverter
+import com.nextcloud.talk.models.json.push.PushConfigurationState
+
+class PushConfigurationConverter {
+    val json = JsonConfiguration.customJsonConfiguration
+
+    @TypeConverter
+    fun fromPushConfigurationToString(pushConfiguration: PushConfigurationState?): String {
+        return if (pushConfiguration == null) {
+            ""
+        } else {
+            json.encodeToString(PushConfigurationState.serializer(), pushConfiguration)
+        }
+    }
+
+    @TypeConverter
+    fun fromStringToPushConfiguration(value: String): PushConfigurationState? {
+        if (value.isBlank()) {
+            return null
+        }
+
+        return json.decodeFromString(PushConfigurationState.serializer(), value)
+    }
+}

+ 48 - 0
app/src/main/java/com/nextcloud/talk/data/source/local/converters/SignalingSettingsConverter.kt

@@ -0,0 +1,48 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Andy Scherzinger
+ * @author Mario Danic
+ * Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
+ * 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.data.source.local.converters
+
+import androidx.room.TypeConverter
+import com.nextcloud.talk.models.json.signaling.settings.SignalingSettings
+
+class SignalingSettingsConverter {
+    val json = JsonConfiguration.customJsonConfiguration
+
+    @TypeConverter
+    fun fromSignalingSettingsToString(signalingSettings: SignalingSettings?): String {
+        return if (signalingSettings == null) {
+            ""
+        } else {
+            json.encodeToString(SignalingSettings.serializer(), signalingSettings)
+        }
+    }
+
+    @TypeConverter
+    fun fromStringToSignalingSettings(value: String): SignalingSettings? {
+        if (value.isBlank()) {
+            return null
+        }
+
+        return json.decodeFromString(SignalingSettings.serializer(), value)
+    }
+}

+ 118 - 0
app/src/main/java/com/nextcloud/talk/data/user/UsersDao.kt

@@ -0,0 +1,118 @@
+/*
+ * 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.data.user
+
+import androidx.lifecycle.LiveData
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+import androidx.room.Transaction
+import androidx.room.Update
+import com.nextcloud.talk.data.user.model.UserNgEntity
+import java.lang.Boolean.FALSE
+import java.lang.Boolean.TRUE
+
+@Dao
+abstract class UsersDao {
+    // get active user
+    @Query("SELECT * FROM users where current = 1")
+    abstract fun getActiveUser(): UserNgEntity?
+
+    @Query("SELECT * FROM users WHERE current = 1")
+    abstract fun getActiveUserLiveData(): LiveData<UserNgEntity?>
+
+    @Query("SELECT * from users ORDER BY current DESC")
+    abstract fun getUsersLiveData(): LiveData<List<UserNgEntity>>
+
+    @Query("SELECT * from users WHERE current != 1 ORDER BY current DESC")
+    abstract fun getUsersLiveDataWithoutActive(): LiveData<List<UserNgEntity>>
+
+    @Query("DELETE FROM users WHERE id = :id")
+    abstract suspend fun deleteUserWithId(id: Long)
+
+    @Update
+    abstract suspend fun updateUser(user: UserNgEntity): Int
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    abstract fun saveUser(user: UserNgEntity): Long
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    abstract suspend fun saveUsers(vararg users: UserNgEntity): List<Long>
+
+    // get all users not scheduled for deletion
+    @Query("SELECT * FROM users where current != 0")
+    abstract fun getUsers(): List<UserNgEntity>
+
+    @Query("SELECT * FROM users where id = :id")
+    abstract fun getUserWithId(id: Long): UserNgEntity
+
+    @Query("SELECT * FROM users where current = 0")
+    abstract fun getUsersScheduledForDeletion(): List<UserNgEntity>
+
+    @Query("SELECT * FROM users WHERE username = :username AND base_url = :server")
+    abstract suspend fun getUserWithUsernameAndServer(username: String, server: String): UserNgEntity?
+
+    @Transaction
+    open suspend fun setUserAsActiveWithId(id: Long) : Boolean {
+        val users = getUsers()
+        for (user in users) {
+            // removed from clause: && UserStatus.ACTIVE == user.status
+            if (user.id != id) {
+                user.current = TRUE
+                updateUser(user)
+            } // removed from clause: && UserStatus.ACTIVE != user.status
+            else if (user.id == id) {
+                user.current = TRUE
+                updateUser(user)
+            }
+        }
+
+        return true
+    }
+
+    @Transaction
+    open suspend fun markUserForDeletion(id: Long): Boolean {
+        val users = getUsers()
+        for (user in users) {
+            if (user.id == id) {
+                // TODO currently we only have a boolean, no intermediate states
+                user.current = FALSE
+                updateUser(user)
+                break
+            }
+        }
+
+        return setAnyUserAsActive()
+    }
+    
+    @Transaction
+    open suspend fun setAnyUserAsActive(): Boolean {
+        val users = getUsers()
+        for (user in users) {
+            user.current = TRUE
+            updateUser(user)
+            return true
+        }
+
+        return false
+    }
+}

+ 87 - 0
app/src/main/java/com/nextcloud/talk/data/user/model/User.kt

@@ -0,0 +1,87 @@
+/*
+ * 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.data.user.model
+
+import android.os.Parcelable
+import com.nextcloud.talk.models.json.capabilities.Capabilities
+import com.nextcloud.talk.models.json.push.PushConfigurationState
+import com.nextcloud.talk.models.json.signaling.settings.SignalingSettings
+import com.nextcloud.talk.utils.ApiUtils
+import kotlinx.android.parcel.Parcelize
+import kotlinx.serialization.Serializable
+
+@Parcelize
+@Serializable
+data class User(
+    var id: Long? = null,
+    var userId: String,
+    var username: String,
+    var baseUrl: String,
+    var token: String? = null,
+    var displayName: String? = null,
+    var pushConfiguration: PushConfigurationState? = null,
+    var capabilities: Capabilities? = null,
+    var clientCertificate: String? = null,
+    var signalingSettings: SignalingSettings? = null,
+    var current: Boolean = java.lang.Boolean.FALSE,
+    var scheduledForDeletion: Boolean = java.lang.Boolean.FALSE
+) : Parcelable
+
+fun User.getMaxMessageLength(): Int {
+    return capabilities?.spreedCapability?.config?.get("chat")?.get("max-length")?.toInt() ?: 1000
+}
+
+fun User.getAttachmentsConfig(key: String): Any? {
+    return capabilities?.spreedCapability?.config?.get("attachments")?.get(key)
+}
+
+fun User.canUserCreateGroupConversations(): Boolean {
+    val canCreateValue = capabilities?.spreedCapability?.config?.get("conversations")?.get("can-create")
+    canCreateValue?.let {
+        return it.toBoolean()
+    }
+    return true
+}
+
+fun User.getCredentials(): String = ApiUtils.getCredentials(username, token)
+
+fun User.hasSpreedFeatureCapability(capabilityName: String): Boolean {
+    return capabilities?.spreedCapability?.features?.contains(capabilityName) ?: false
+}
+
+fun User.toUserEntity(): UserNgEntity {
+    var userNgEntity: UserNgEntity? = null
+    this.id?.let {
+        userNgEntity = UserNgEntity(it, userId, username, baseUrl)
+    } ?: run {
+        userNgEntity = UserNgEntity(userId = this.userId, username = this.username, baseUrl = this.baseUrl)
+    }
+
+    userNgEntity!!.token = this.token
+    userNgEntity!!.displayName = this.displayName
+    userNgEntity!!.pushConfiguration = this.pushConfiguration
+    userNgEntity!!.capabilities = this.capabilities
+    userNgEntity!!.clientCertificate = this.clientCertificate
+    userNgEntity!!.externalSignalingServer = this.signalingSettings
+    userNgEntity!!.current = this.current
+    userNgEntity!!.scheduledForDeletion = this.scheduledForDeletion
+
+    return userNgEntity!!
+}

+ 73 - 0
app/src/main/java/com/nextcloud/talk/data/user/model/UserNgEntity.kt

@@ -0,0 +1,73 @@
+/*
+ * 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.data.user.model
+
+import android.os.Parcelable
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+import com.nextcloud.talk.models.json.capabilities.Capabilities
+import com.nextcloud.talk.models.json.push.PushConfigurationState
+import com.nextcloud.talk.models.json.signaling.settings.SignalingSettings
+import com.nextcloud.talk.utils.ApiUtils
+import kotlinx.android.parcel.Parcelize
+import kotlinx.serialization.Serializable
+import java.lang.Boolean.FALSE
+
+@Parcelize
+@Serializable
+@Entity(tableName = "users")
+data class UserNgEntity(
+    @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") var id: Long = 0,
+    @ColumnInfo(name = "user_id") var userId: String,
+    @ColumnInfo(name = "username") var username: String,
+    @ColumnInfo(name = "base_url") var baseUrl: String,
+    @ColumnInfo(name = "token") var token: String? = null,
+    @ColumnInfo(name = "display_name") var displayName: String? = null,
+    @ColumnInfo(name = "push_configuration_state") var pushConfiguration: PushConfigurationState? = null,
+    @ColumnInfo(name = "capabilities") var capabilities: Capabilities? = null,
+    @ColumnInfo(name = "client_certificate") var clientCertificate: String? = null,
+    @ColumnInfo(name = "external_signaling_server") var externalSignalingServer: SignalingSettings? = null,
+    @ColumnInfo(name = "current") var current: Boolean = FALSE,
+    @ColumnInfo(name = "scheduled_for_deletion") var scheduledForDeletion: Boolean = FALSE,
+) : Parcelable {
+
+    fun hasSpreedFeatureCapability(capabilityName: String): Boolean {
+        return capabilities?.spreedCapability?.features?.contains(capabilityName) ?: false
+
+    }
+}
+
+fun UserNgEntity.canUserCreateGroupConversations(): Boolean {
+    val canCreateValue = capabilities?.spreedCapability?.config?.get("conversations")?.get("can-create")
+    canCreateValue?.let {
+        return it.toBoolean()
+    }
+    return true
+}
+
+fun UserNgEntity.toUser(): User {
+    return User(this.id, this.userId, this.username, this.baseUrl, this.token, this.displayName, this
+        .pushConfiguration, this.capabilities, this.clientCertificate, this.externalSignalingServer, this.current,
+        this.scheduledForDeletion)
+}
+
+fun UserNgEntity.getCredentials(): String = ApiUtils.getCredentials(username, token)

+ 2 - 0
app/src/main/java/com/nextcloud/talk/models/json/capabilities/Capabilities.kt

@@ -25,9 +25,11 @@ import android.os.Parcelable
 import com.bluelinelabs.logansquare.annotation.JsonField
 import com.bluelinelabs.logansquare.annotation.JsonObject
 import kotlinx.android.parcel.Parcelize
+import kotlinx.serialization.Serializable
 
 @Parcelize
 @JsonObject
+@Serializable
 data class Capabilities(
     @JsonField(name = ["spreed"])
     var spreedCapability: SpreedCapability?,

+ 2 - 0
app/src/main/java/com/nextcloud/talk/models/json/capabilities/NotificationsCapability.kt

@@ -25,9 +25,11 @@ import android.os.Parcelable
 import com.bluelinelabs.logansquare.annotation.JsonField
 import com.bluelinelabs.logansquare.annotation.JsonObject
 import kotlinx.android.parcel.Parcelize
+import kotlinx.serialization.Serializable
 
 @Parcelize
 @JsonObject
+@Serializable
 data class NotificationsCapability(
     @JsonField(name = ["ocs-endpoints"])
     var features: List<String>?

+ 2 - 0
app/src/main/java/com/nextcloud/talk/models/json/capabilities/ProvisioningCapability.kt

@@ -25,9 +25,11 @@ import android.os.Parcelable
 import com.bluelinelabs.logansquare.annotation.JsonField
 import com.bluelinelabs.logansquare.annotation.JsonObject
 import kotlinx.android.parcel.Parcelize
+import kotlinx.serialization.Serializable
 
 @Parcelize
 @JsonObject
+@Serializable
 data class ProvisioningCapability(
     @JsonField(name = ["AccountPropertyScopesVersion"])
     var accountPropertyScopesVersion: Int?

+ 2 - 0
app/src/main/java/com/nextcloud/talk/models/json/capabilities/SpreedCapability.kt

@@ -25,9 +25,11 @@ import android.os.Parcelable
 import com.bluelinelabs.logansquare.annotation.JsonField
 import com.bluelinelabs.logansquare.annotation.JsonObject
 import kotlinx.android.parcel.Parcelize
+import kotlinx.serialization.Serializable
 
 @Parcelize
 @JsonObject
+@Serializable
 data class SpreedCapability(
     @JsonField(name = ["features"])
     var features: List<String>?,

+ 2 - 0
app/src/main/java/com/nextcloud/talk/models/json/capabilities/ThemingCapability.kt

@@ -25,9 +25,11 @@ import android.os.Parcelable
 import com.bluelinelabs.logansquare.annotation.JsonField
 import com.bluelinelabs.logansquare.annotation.JsonObject
 import kotlinx.android.parcel.Parcelize
+import kotlinx.serialization.Serializable
 
 @Parcelize
 @JsonObject
+@Serializable
 data class ThemingCapability(
     @JsonField(name = ["name"])
     var name: String?,

+ 2 - 0
app/src/main/java/com/nextcloud/talk/models/json/capabilities/UserStatusCapability.kt

@@ -25,9 +25,11 @@ import android.os.Parcelable
 import com.bluelinelabs.logansquare.annotation.JsonField
 import com.bluelinelabs.logansquare.annotation.JsonObject
 import kotlinx.android.parcel.Parcelize
+import kotlinx.serialization.Serializable
 
 @Parcelize
 @JsonObject
+@Serializable
 data class UserStatusCapability(
     @JsonField(name = ["enabled"])
     var enabled: Boolean,

+ 2 - 0
app/src/main/java/com/nextcloud/talk/models/json/push/PushConfigurationState.kt

@@ -25,9 +25,11 @@ import android.os.Parcelable
 import com.bluelinelabs.logansquare.annotation.JsonField
 import com.bluelinelabs.logansquare.annotation.JsonObject
 import kotlinx.android.parcel.Parcelize
+import kotlinx.serialization.Serializable
 
 @Parcelize
 @JsonObject
+@Serializable
 data class PushConfigurationState(
     @JsonField(name = ["pushToken"])
     var pushToken: String?,

+ 2 - 0
app/src/main/java/com/nextcloud/talk/models/json/signaling/settings/IceServer.kt

@@ -25,9 +25,11 @@ import android.os.Parcelable
 import com.bluelinelabs.logansquare.annotation.JsonField
 import com.bluelinelabs.logansquare.annotation.JsonObject
 import kotlinx.android.parcel.Parcelize
+import kotlinx.serialization.Serializable
 
 @Parcelize
 @JsonObject
+@Serializable
 data class IceServer(
     @Deprecated("")
     @JsonField(name = ["url"])

+ 3 - 1
app/src/main/java/com/nextcloud/talk/models/json/signaling/settings/Settings.kt → app/src/main/java/com/nextcloud/talk/models/json/signaling/settings/SignalingSettings.kt

@@ -25,10 +25,12 @@ import android.os.Parcelable
 import com.bluelinelabs.logansquare.annotation.JsonField
 import com.bluelinelabs.logansquare.annotation.JsonObject
 import kotlinx.android.parcel.Parcelize
+import kotlinx.serialization.Serializable
 
 @Parcelize
 @JsonObject
-data class Settings(
+@Serializable
+data class SignalingSettings(
     @JsonField(name = ["stunservers"])
     var stunServers: List<IceServer>? = null,
     @JsonField(name = ["turnservers"])

+ 1 - 1
app/src/main/java/com/nextcloud/talk/models/json/signaling/settings/SignalingSettingsOcs.kt

@@ -33,7 +33,7 @@ data class SignalingSettingsOcs(
     @JsonField(name = ["meta"])
     var meta: GenericMeta?,
     @JsonField(name = ["data"])
-    var settings: Settings? = null
+    var settings: SignalingSettings? = null
 ) : Parcelable {
     // This constructor is added to work with the 'com.bluelinelabs.logansquare.annotation.JsonObject'
     constructor() : this(null, null)

+ 1 - 0
build.gradle

@@ -36,6 +36,7 @@ buildscript {
     dependencies {
         classpath 'com.android.tools.build:gradle:7.2.1'
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}"
+        classpath "org.jetbrains.kotlin:kotlin-serialization:${kotlinVersion}"
         classpath 'gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:4.7.5'
         classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.20.0"
         classpath "org.jlleitschuh.gradle:ktlint-gradle:10.3.0"