From 5ffa3c44fd05c6c8fdda1bcaf04fbab8f9c2087d Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Mon, 20 Jun 2022 13:46:32 +0200 Subject: [PATCH] create new capabilities util add license header and format kotlin code Signed-off-by: Andy Scherzinger --- .../nextcloud/talk/activities/MainActivity.kt | 1 - .../talk/controllers/SettingsController.kt | 11 +- .../talk/dagger/modules/RepositoryModule.kt | 6 +- .../talk/data/source/local/Migrations.kt | 135 ++++++---- .../talk/data/source/local/TalkDatabase.kt | 2 +- .../ExternalSignalingServerConverter.kt | 1 - .../converters/HashMapHashMapConverter.kt | 2 +- .../local/converters/JsonConfiguration.kt | 2 +- .../com/nextcloud/talk/data/user/UsersDao.kt | 4 +- .../talk/data/user/UsersRepository.kt | 2 +- .../nextcloud/talk/data/user/model/User.kt | 1 - .../models/database/CapabilitiesUtil.java | 51 ---- .../nextcloud/talk/models/database/User.java | 1 - .../com/nextcloud/talk/users/UserManager.kt | 11 +- .../database/user/CapabilitiesNgUtil.java | 230 ++++++++++++++++++ 15 files changed, 335 insertions(+), 125 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/talk/utils/database/user/CapabilitiesNgUtil.java diff --git a/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt index d6a803ad9..10bf10f84 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt @@ -65,7 +65,6 @@ import io.reactivex.schedulers.Schedulers import io.requery.Persistable import io.requery.android.sqlcipher.SqlCipherDatabaseSource import io.requery.reactivex.ReactiveEntityStore -import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import org.parceler.Parcels diff --git a/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt b/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt index a2a97edac..d6593607a 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt @@ -69,7 +69,6 @@ import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.setAppT import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication import com.nextcloud.talk.controllers.base.NewBaseController import com.nextcloud.talk.controllers.util.viewBinding -import com.nextcloud.talk.data.storage.ArbitraryStoragesRepository import com.nextcloud.talk.data.user.UsersRepository import com.nextcloud.talk.data.user.model.UserNgEntity import com.nextcloud.talk.databinding.ControllerSettingsBinding @@ -89,6 +88,7 @@ import com.nextcloud.talk.utils.NotificationUtils.getCallRingtoneUri import com.nextcloud.talk.utils.NotificationUtils.getMessageRingtoneUri import com.nextcloud.talk.utils.SecurityUtils import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ARE_CALL_SOUNDS +import com.nextcloud.talk.utils.database.user.CapabilitiesNgUtil import com.nextcloud.talk.utils.database.user.UserUtils import com.nextcloud.talk.utils.preferences.MagicUserInputModule import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder @@ -103,7 +103,6 @@ import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody import java.net.URI import java.net.URISyntaxException -import java.util.ArrayList import java.util.Arrays import java.util.Locale import javax.inject.Inject @@ -190,7 +189,7 @@ class SettingsController : NewBaseController(R.layout.controller_settings) { } private fun setupPhoneBookIntegration() { - if (CapabilitiesUtil.isPhoneBookIntegrationAvailable(userRepository.getActiveUser())) { + if (CapabilitiesNgUtil.isPhoneBookIntegrationAvailable(userRepository.getActiveUser())) { binding.settingsPhoneBookIntegration.visibility = View.VISIBLE } else { binding.settingsPhoneBookIntegration.visibility = View.GONE @@ -645,7 +644,7 @@ class SettingsController : NewBaseController(R.layout.controller_settings) { private fun setupServerAgeWarning() { when { - CapabilitiesUtil.isServerEOL(currentUser) -> { + CapabilitiesNgUtil.isServerEOL(currentUser) -> { binding.serverAgeWarningText.setTextColor(ContextCompat.getColor((context)!!, R.color.nc_darkRed)) binding.serverAgeWarningText.setText(R.string.nc_settings_server_eol) binding.serverAgeWarningIcon.setColorFilter( @@ -653,7 +652,7 @@ class SettingsController : NewBaseController(R.layout.controller_settings) { PorterDuff.Mode.SRC_IN ) } - CapabilitiesUtil.isServerAlmostEOL(currentUser) -> { + CapabilitiesNgUtil.isServerAlmostEOL(currentUser) -> { binding.serverAgeWarningText.setTextColor( ContextCompat.getColor((context)!!, R.color.nc_darkYellow) ) @@ -685,7 +684,7 @@ class SettingsController : NewBaseController(R.layout.controller_settings) { if (CapabilitiesUtil.isReadStatusAvailable(userUtils.currentUser)) { (binding.settingsReadPrivacy.findViewById(R.id.mp_checkable) as Checkable).isChecked = - !CapabilitiesUtil.isReadStatusPrivate(currentUser) + !CapabilitiesNgUtil.isReadStatusPrivate(currentUser) } else { binding.settingsReadPrivacy.visibility = View.GONE } diff --git a/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt b/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt index 68ec493b6..bb8a5f255 100644 --- a/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt +++ b/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt @@ -2,6 +2,8 @@ * Nextcloud Talk application * * @author Álvaro Brey + * @author Andy Scherzinger + * Copyright (C) 2022 Andy Scherzinger * Copyright (C) 2022 Álvaro Brey * Copyright (C) 2022 Nextcloud GmbH * @@ -57,12 +59,12 @@ class RepositoryModule { } @Provides - fun provideUsersRepository(database : TalkDatabase): UsersRepository { + fun provideUsersRepository(database: TalkDatabase): UsersRepository { return UsersRepositoryImpl(database.usersDao()) } @Provides - fun provideArbitraryStoragesRepository(database : TalkDatabase): ArbitraryStoragesRepository { + fun provideArbitraryStoragesRepository(database: TalkDatabase): ArbitraryStoragesRepository { return ArbitraryStoragesRepositoryImpl(database.arbitraryStoragesDao()) } } diff --git a/app/src/main/java/com/nextcloud/talk/data/source/local/Migrations.kt b/app/src/main/java/com/nextcloud/talk/data/source/local/Migrations.kt index 4123feabd..a3d23dfec 100644 --- a/app/src/main/java/com/nextcloud/talk/data/source/local/Migrations.kt +++ b/app/src/main/java/com/nextcloud/talk/data/source/local/Migrations.kt @@ -1,62 +1,91 @@ +/* + * Nextcloud Talk application + * + * @author Andy Scherzinger + * Copyright (C) 2022 Andy Scherzinger + * + * 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 . + */ + package com.nextcloud.talk.data.source.local import androidx.room.migration.Migration import androidx.sqlite.db.SupportSQLiteDatabase object Migrations { - val MIGRATION_7_8 = object : Migration(7, 8) { + val MIGRATION_6_8 = object : Migration(6, 8) { override fun migrate(database: SupportSQLiteDatabase) { - // Create the new tables - database.execSQL( - "CREATE TABLE User_new (" + - "id INTEGER NOT NULL, " + - "userId TEXT, " + - "username TEXT, " + - "baseUrl TEXT, " + - "token TEXT, " + - "displayName TEXT, " + - "pushConfigurationState TEXT, " + - "capabilities TEXT, " + - "clientCertificate TEXT, " + - "externalSignalingServer TEXT, " + - "current INTEGER NOT NULL, " + - "scheduledForDeletion INTEGER NOT NULL, " + - "PRIMARY KEY(id)" + - ")" - ) - database.execSQL( - "CREATE TABLE ArbitraryStorage_new (" + - "accountIdentifier INTEGER NOT NULL, " + - "\"key\" TEXT, " + - "object TEXT, " + - "value TEXT, " + - "PRIMARY KEY(accountIdentifier)" + - ")" - ) - // Copy the data - database.execSQL( - "INSERT INTO User_new (" + - "id, userId, username, baseUrl, token, displayName, pushConfigurationState, capabilities, " + - "clientCertificate, externalSignalingServer, current, scheduledForDeletion) " + - "SELECT " + - "id, userId, username, baseUrl, token, displayName, pushConfigurationState, capabilities, " + - "clientCertificate, externalSignalingServer, current, scheduledForDeletion " + - "FROM User" - ) - database.execSQL( - "INSERT INTO ArbitraryStorage_new (" + - "accountIdentifier, \"key\", object, value) " + - "SELECT " + - "accountIdentifier, \"key\", object, value " + - "FROM ArbitraryStorage" - ) - // Remove the old table - database.execSQL("DROP TABLE User") - database.execSQL("DROP TABLE ArbitraryStorage") - - // Change the table name to the correct one - database.execSQL("ALTER TABLE User_new RENAME TO User") - database.execSQL("ALTER TABLE ArbitraryStorage_new RENAME TO ArbitraryStorage") + migrateToRoom(database) } } -} \ No newline at end of file + + val MIGRATION_7_8 = object : Migration(7, 8) { + override fun migrate(database: SupportSQLiteDatabase) { + migrateToRoom(database) + } + } + + fun migrateToRoom(database: SupportSQLiteDatabase) { + database.execSQL( + "CREATE TABLE User_new (" + + "id INTEGER NOT NULL, " + + "userId TEXT, " + + "username TEXT, " + + "baseUrl TEXT, " + + "token TEXT, " + + "displayName TEXT, " + + "pushConfigurationState TEXT, " + + "capabilities TEXT, " + + "clientCertificate TEXT, " + + "externalSignalingServer TEXT, " + + "current INTEGER NOT NULL, " + + "scheduledForDeletion INTEGER NOT NULL, " + + "PRIMARY KEY(id)" + + ")" + ) + database.execSQL( + "CREATE TABLE ArbitraryStorage_new (" + + "accountIdentifier INTEGER NOT NULL, " + + "\"key\" TEXT, " + + "object TEXT, " + + "value TEXT, " + + "PRIMARY KEY(accountIdentifier)" + + ")" + ) + // Copy the data + database.execSQL( + "INSERT INTO User_new (" + + "id, userId, username, baseUrl, token, displayName, pushConfigurationState, capabilities, " + + "clientCertificate, externalSignalingServer, current, scheduledForDeletion) " + + "SELECT " + + "id, userId, username, baseUrl, token, displayName, pushConfigurationState, capabilities, " + + "clientCertificate, externalSignalingServer, current, scheduledForDeletion " + + "FROM User" + ) + database.execSQL( + "INSERT INTO ArbitraryStorage_new (" + + "accountIdentifier, \"key\", object, value) " + + "SELECT " + + "accountIdentifier, \"key\", object, value " + + "FROM ArbitraryStorage" + ) + // Remove the old table + database.execSQL("DROP TABLE User") + database.execSQL("DROP TABLE ArbitraryStorage") + + // Change the table name to the correct one + database.execSQL("ALTER TABLE User_new RENAME TO User") + database.execSQL("ALTER TABLE ArbitraryStorage_new RENAME TO ArbitraryStorage") + } +} diff --git a/app/src/main/java/com/nextcloud/talk/data/source/local/TalkDatabase.kt b/app/src/main/java/com/nextcloud/talk/data/source/local/TalkDatabase.kt index c80a1f9f3..c6da1d53c 100644 --- a/app/src/main/java/com/nextcloud/talk/data/source/local/TalkDatabase.kt +++ b/app/src/main/java/com/nextcloud/talk/data/source/local/TalkDatabase.kt @@ -83,7 +83,7 @@ abstract class TalkDatabase : RoomDatabase() { return Room .databaseBuilder(context.applicationContext, TalkDatabase::class.java, dbName) .openHelperFactory(factory) - .addMigrations(Migrations.MIGRATION_7_8) + .addMigrations(Migrations.MIGRATION_6_8, Migrations.MIGRATION_7_8) .allowMainThreadQueries() .addCallback( object : RoomDatabase.Callback() { diff --git a/app/src/main/java/com/nextcloud/talk/data/source/local/converters/ExternalSignalingServerConverter.kt b/app/src/main/java/com/nextcloud/talk/data/source/local/converters/ExternalSignalingServerConverter.kt index e1f949bc3..71dd1fac4 100644 --- a/app/src/main/java/com/nextcloud/talk/data/source/local/converters/ExternalSignalingServerConverter.kt +++ b/app/src/main/java/com/nextcloud/talk/data/source/local/converters/ExternalSignalingServerConverter.kt @@ -22,7 +22,6 @@ package com.nextcloud.talk.data.source.local.converters import androidx.room.TypeConverter import com.nextcloud.talk.models.ExternalSignalingServer -import com.nextcloud.talk.models.json.signaling.settings.SignalingSettings class ExternalSignalingServerConverter { val json = JsonConfiguration.customJsonConfiguration diff --git a/app/src/main/java/com/nextcloud/talk/data/source/local/converters/HashMapHashMapConverter.kt b/app/src/main/java/com/nextcloud/talk/data/source/local/converters/HashMapHashMapConverter.kt index 019ecba35..a40220a82 100644 --- a/app/src/main/java/com/nextcloud/talk/data/source/local/converters/HashMapHashMapConverter.kt +++ b/app/src/main/java/com/nextcloud/talk/data/source/local/converters/HashMapHashMapConverter.kt @@ -41,4 +41,4 @@ class HashMapHashMapConverter { return LoganSquare.parseMap(value, HashMap::class.java) as HashMap>? } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/nextcloud/talk/data/source/local/converters/JsonConfiguration.kt b/app/src/main/java/com/nextcloud/talk/data/source/local/converters/JsonConfiguration.kt index 8ea6e8ffe..6f40e18c3 100644 --- a/app/src/main/java/com/nextcloud/talk/data/source/local/converters/JsonConfiguration.kt +++ b/app/src/main/java/com/nextcloud/talk/data/source/local/converters/JsonConfiguration.kt @@ -27,7 +27,7 @@ import kotlinx.serialization.json.Json sealed class JsonConfiguration { companion object { val customJsonConfiguration = Json { - prettyPrint = true; + prettyPrint = true useArrayPolymorphism = true } } diff --git a/app/src/main/java/com/nextcloud/talk/data/user/UsersDao.kt b/app/src/main/java/com/nextcloud/talk/data/user/UsersDao.kt index 30955ec16..0fdbf3af5 100644 --- a/app/src/main/java/com/nextcloud/talk/data/user/UsersDao.kt +++ b/app/src/main/java/com/nextcloud/talk/data/user/UsersDao.kt @@ -89,7 +89,7 @@ abstract class UsersDao { abstract suspend fun getUserWithUsernameAndServer(username: String, server: String): UserNgEntity? @Transaction - open suspend fun setUserAsActiveWithId(id: Long) : Boolean { + open suspend fun setUserAsActiveWithId(id: Long): Boolean { val users = getUsers() for (user in users) { // removed from clause: && UserStatus.ACTIVE == user.status @@ -120,7 +120,7 @@ abstract class UsersDao { return setAnyUserAsActive() } - + @Transaction open suspend fun setAnyUserAsActive(): Boolean { val users = getUsers() diff --git a/app/src/main/java/com/nextcloud/talk/data/user/UsersRepository.kt b/app/src/main/java/com/nextcloud/talk/data/user/UsersRepository.kt index 02f0b4313..19596ae9e 100644 --- a/app/src/main/java/com/nextcloud/talk/data/user/UsersRepository.kt +++ b/app/src/main/java/com/nextcloud/talk/data/user/UsersRepository.kt @@ -46,4 +46,4 @@ interface UsersRepository { suspend fun deleteUserWithId(id: Long) suspend fun setAnyUserAsActive(): Boolean suspend fun markUserForDeletion(id: Long): Boolean -} \ No newline at end of file +} diff --git a/app/src/main/java/com/nextcloud/talk/data/user/model/User.kt b/app/src/main/java/com/nextcloud/talk/data/user/model/User.kt index fe4a3472d..564f0722f 100644 --- a/app/src/main/java/com/nextcloud/talk/data/user/model/User.kt +++ b/app/src/main/java/com/nextcloud/talk/data/user/model/User.kt @@ -23,7 +23,6 @@ import android.os.Parcelable import com.nextcloud.talk.models.ExternalSignalingServer 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 diff --git a/app/src/main/java/com/nextcloud/talk/models/database/CapabilitiesUtil.java b/app/src/main/java/com/nextcloud/talk/models/database/CapabilitiesUtil.java index 929d328a0..135946486 100644 --- a/app/src/main/java/com/nextcloud/talk/models/database/CapabilitiesUtil.java +++ b/app/src/main/java/com/nextcloud/talk/models/database/CapabilitiesUtil.java @@ -24,7 +24,6 @@ package com.nextcloud.talk.models.database; import android.util.Log; import com.bluelinelabs.logansquare.LoganSquare; -import com.nextcloud.talk.data.user.model.UserNgEntity; import com.nextcloud.talk.models.json.capabilities.Capabilities; import java.io.IOException; @@ -67,18 +66,6 @@ public abstract class CapabilitiesUtil { return false; } - @Deprecated - public static boolean isServerEOL(@Nullable UserNgEntity user) { - // Capability is available since Talk 4 => Nextcloud 14 => Autmn 2018 - return !hasSpreedFeatureCapability(user, "no-ping"); - } - - @Deprecated - public static boolean isServerAlmostEOL(@Nullable UserNgEntity user) { - // Capability is available since Talk 8 => Nextcloud 18 => January 2020 - return !hasSpreedFeatureCapability(user, "chat-replies"); - } - @Deprecated public static boolean isServerEOL(@Nullable UserEntity user) { // Capability is available since Talk 4 => Nextcloud 14 => Autmn 2018 @@ -95,17 +82,6 @@ public abstract class CapabilitiesUtil { return hasSpreedFeatureCapability(user, "chat-read-marker"); } - public static boolean hasSpreedFeatureCapability(@Nullable UserNgEntity user, String capabilityName) { - if (user != null && user.getCapabilities() != null) { - Capabilities capabilities = user.getCapabilities(); - if (capabilities != null && capabilities.getSpreedCapability() != null && - capabilities.getSpreedCapability().getFeatures() != null) { - return capabilities.getSpreedCapability().getFeatures().contains(capabilityName); - } - } - return false; - } - @Deprecated public static boolean hasSpreedFeatureCapability(@Nullable UserEntity user, String capabilityName) { if (user != null && user.getCapabilities() != null) { @@ -166,17 +142,6 @@ public abstract class CapabilitiesUtil { return false; } - public static boolean isPhoneBookIntegrationAvailable(@Nullable UserNgEntity user) { - if (user != null && user.getCapabilities() != null) { - Capabilities capabilities = user.getCapabilities(); - return capabilities != null && - capabilities.getSpreedCapability() != null && - capabilities.getSpreedCapability().getFeatures() != null && - capabilities.getSpreedCapability().getFeatures().contains("phonebook-search"); - } - return false; - } - public static boolean isReadStatusAvailable(@Nullable UserEntity user) { if (user != null && user.getCapabilities() != null) { try { @@ -216,22 +181,6 @@ public abstract class CapabilitiesUtil { return false; } - public static boolean isReadStatusPrivate(@Nullable UserNgEntity user) { - if (user != null && user.getCapabilities() != null) { - Capabilities capabilities = user.getCapabilities(); - if (capabilities != null && - capabilities.getSpreedCapability() != null && - capabilities.getSpreedCapability().getConfig() != null && - capabilities.getSpreedCapability().getConfig().containsKey("chat")) { - HashMap map = capabilities.getSpreedCapability().getConfig().get("chat"); - if (map != null && map.containsKey("read-privacy")) { - return Integer.parseInt(map.get("read-privacy")) == 1; - } - } - } - return false; - } - public static boolean isUserStatusAvailable(@Nullable UserEntity user) { if (user != null && user.getCapabilities() != null) { try { diff --git a/app/src/main/java/com/nextcloud/talk/models/database/User.java b/app/src/main/java/com/nextcloud/talk/models/database/User.java index fd966dee3..47e9fac7e 100644 --- a/app/src/main/java/com/nextcloud/talk/models/database/User.java +++ b/app/src/main/java/com/nextcloud/talk/models/database/User.java @@ -29,7 +29,6 @@ import io.requery.Entity; import io.requery.Generated; import io.requery.Key; import io.requery.Persistable; -import io.requery.Table; @Entity public interface User extends Parcelable, Persistable, Serializable { diff --git a/app/src/main/java/com/nextcloud/talk/users/UserManager.kt b/app/src/main/java/com/nextcloud/talk/users/UserManager.kt index 8f4786cfe..5b4fa14c1 100644 --- a/app/src/main/java/com/nextcloud/talk/users/UserManager.kt +++ b/app/src/main/java/com/nextcloud/talk/users/UserManager.kt @@ -114,7 +114,8 @@ class UserManager internal constructor(private val userRepository: UsersReposito } suspend fun createOrUpdateUser( - username: String?, token: String?, + username: String?, + token: String?, serverUrl: String?, displayName: String?, pushConfigurationState: String?, @@ -166,8 +167,12 @@ class UserManager internal constructor(private val userRepository: UsersReposito if (token != null && token != user.token) { user.token = token } - if (displayName != null && user.displayName == null || displayName != null && (user.displayName - != null) && displayName != user.displayName + if ( + displayName != null && + user.displayName == null || + displayName != null && + (user.displayName != null) && + displayName != user.displayName ) { user.displayName = displayName } diff --git a/app/src/main/java/com/nextcloud/talk/utils/database/user/CapabilitiesNgUtil.java b/app/src/main/java/com/nextcloud/talk/utils/database/user/CapabilitiesNgUtil.java new file mode 100644 index 000000000..010bf98e0 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/utils/database/user/CapabilitiesNgUtil.java @@ -0,0 +1,230 @@ +/* + * Nextcloud Talk application + * + * @author Andy Scherzinger + * @author Mario Danic + * Copyright (C) 2021 Andy Scherzinger (info@andy-scherzinger.de) + * Copyright (C) 2017-2018 Mario Danic + * + * 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 . + */ +package com.nextcloud.talk.utils.database.user; + +import com.nextcloud.talk.data.user.model.UserNgEntity; +import com.nextcloud.talk.models.json.capabilities.Capabilities; + +import java.util.HashMap; +import java.util.Map; + +import androidx.annotation.Nullable; + +public abstract class CapabilitiesNgUtil { + private static final String TAG = CapabilitiesNgUtil.class.getSimpleName(); + + public static boolean hasNotificationsCapability(@Nullable UserNgEntity user, String capabilityName) { + if (user != null && user.getCapabilities() != null) { + Capabilities capabilities = user.getCapabilities(); + if (capabilities.getNotificationsCapability() != null && + capabilities.getNotificationsCapability().getFeatures() != null) { + return capabilities.getSpreedCapability().getFeatures().contains(capabilityName); + } + } + return false; + } + + public static boolean hasExternalCapability(@Nullable UserNgEntity user, String capabilityName) { + if (user != null && user.getCapabilities() != null) { + Capabilities capabilities = user.getCapabilities(); + if (capabilities.getExternalCapability() != null && + capabilities.getExternalCapability().containsKey("v1")) { + return capabilities.getExternalCapability().get("v1").contains(capabilityName); + } + } + return false; + } + + public static boolean isServerEOL(@Nullable UserNgEntity user) { + // Capability is available since Talk 4 => Nextcloud 14 => Autmn 2018 + return !hasSpreedFeatureCapability(user, "no-ping"); + } + + public static boolean isServerAlmostEOL(@Nullable UserNgEntity user) { + // Capability is available since Talk 8 => Nextcloud 18 => January 2020 + return !hasSpreedFeatureCapability(user, "chat-replies"); + } + + public static boolean canSetChatReadMarker(@Nullable UserNgEntity user) { + return hasSpreedFeatureCapability(user, "chat-read-marker"); + } + + public static boolean hasSpreedFeatureCapability(@Nullable UserNgEntity user, String capabilityName) { + if (user != null && user.getCapabilities() != null) { + Capabilities capabilities = user.getCapabilities(); + if (capabilities != null && capabilities.getSpreedCapability() != null && + capabilities.getSpreedCapability().getFeatures() != null) { + return capabilities.getSpreedCapability().getFeatures().contains(capabilityName); + } + } + return false; + } + + public static Integer getMessageMaxLength(@Nullable UserNgEntity user) { + if (user != null && user.getCapabilities() != null) { + Capabilities capabilities = user.getCapabilities(); + if (capabilities != null && + capabilities.getSpreedCapability() != null && + capabilities.getSpreedCapability().getConfig() != null && + capabilities.getSpreedCapability().getConfig().containsKey("chat")) { + HashMap chatConfigHashMap = capabilities + .getSpreedCapability() + .getConfig() + .get("chat"); + if (chatConfigHashMap != null && chatConfigHashMap.containsKey("max-length")) { + int chatSize = Integer.parseInt(chatConfigHashMap.get("max-length")); + if (chatSize > 0) { + return chatSize; + } else { + return 1000; + } + } + } + } + return 1000; + } + + public static boolean isPhoneBookIntegrationAvailable(@Nullable UserNgEntity user) { + if (user != null && user.getCapabilities() != null) { + Capabilities capabilities = user.getCapabilities(); + return capabilities != null && + capabilities.getSpreedCapability() != null && + capabilities.getSpreedCapability().getFeatures() != null && + capabilities.getSpreedCapability().getFeatures().contains("phonebook-search"); + } + return false; + } + + public static boolean isReadStatusAvailable(@Nullable UserNgEntity user) { + if (user != null && user.getCapabilities() != null) { + Capabilities capabilities = user.getCapabilities(); + if (capabilities != null && + capabilities.getSpreedCapability() != null && + capabilities.getSpreedCapability().getConfig() != null && + capabilities.getSpreedCapability().getConfig().containsKey("chat")) { + Map map = capabilities.getSpreedCapability().getConfig().get("chat"); + return map != null && map.containsKey("read-privacy"); + } + } + return false; + } + + public static boolean isReadStatusPrivate(@Nullable UserNgEntity user) { + if (user != null && user.getCapabilities() != null) { + Capabilities capabilities = user.getCapabilities(); + if (capabilities != null && + capabilities.getSpreedCapability() != null && + capabilities.getSpreedCapability().getConfig() != null && + capabilities.getSpreedCapability().getConfig().containsKey("chat")) { + HashMap map = capabilities.getSpreedCapability().getConfig().get("chat"); + if (map != null && map.containsKey("read-privacy")) { + return Integer.parseInt(map.get("read-privacy")) == 1; + } + } + } + return false; + } + + public static boolean isUserStatusAvailable(@Nullable UserNgEntity user) { + if (user != null && user.getCapabilities() != null) { + Capabilities capabilities = user.getCapabilities(); + if (capabilities.getUserStatusCapability() != null && + capabilities.getUserStatusCapability().getEnabled() && + capabilities.getUserStatusCapability().getSupportsEmoji()) { + return true; + } + } + return false; + } + + public static String getAttachmentFolder(@Nullable UserNgEntity user) { + if (user != null && user.getCapabilities() != null) { + Capabilities capabilities = user.getCapabilities(); + if (capabilities != null && + capabilities.getSpreedCapability() != null && + capabilities.getSpreedCapability().getConfig() != null && + capabilities.getSpreedCapability().getConfig().containsKey("attachments")) { + HashMap map = capabilities.getSpreedCapability().getConfig().get("attachments"); + if (map != null && map.containsKey("folder")) { + return map.get("folder"); + } + } + } + return "/Talk"; + } + + public static String getServerName(@Nullable UserNgEntity user) { + if (user != null && user.getCapabilities() != null) { + Capabilities capabilities = user.getCapabilities(); + if (capabilities != null && capabilities.getThemingCapability() != null) { + return capabilities.getThemingCapability().getName(); + } + } + return ""; + } + + // TODO later avatar can also be checked via user fields, for now it is in Talk capability + public static boolean isAvatarEndpointAvailable(@Nullable UserNgEntity user) { + if (user != null && user.getCapabilities() != null) { + Capabilities capabilities = user.getCapabilities(); + return (capabilities != null && + capabilities.getSpreedCapability() != null && + capabilities.getSpreedCapability().getFeatures() != null && + capabilities.getSpreedCapability().getFeatures().contains("temp-user-avatar-api")); + } + return false; + } + + public static boolean canEditScopes(@Nullable UserNgEntity user) { + if (user != null && user.getCapabilities() != null) { + Capabilities capabilities = user.getCapabilities(); + return (capabilities != null && + capabilities.getProvisioningCapability() != null && + capabilities.getProvisioningCapability().getAccountPropertyScopesVersion() != null && + capabilities.getProvisioningCapability().getAccountPropertyScopesVersion() > 1); + } + return false; + } + + public static boolean isAbleToCall(@Nullable UserNgEntity user) { + if (user != null && user.getCapabilities() != null) { + Capabilities capabilities = user.getCapabilities(); + if (capabilities != null && + capabilities.getSpreedCapability() != null && + capabilities.getSpreedCapability().getConfig() != null && + capabilities.getSpreedCapability().getConfig().containsKey("call") && + capabilities.getSpreedCapability().getConfig().get("call") != null && + capabilities.getSpreedCapability().getConfig().get("call").containsKey("enabled")) { + return Boolean.parseBoolean( + capabilities.getSpreedCapability().getConfig().get("call").get("enabled")); + } else { + // older nextcloud versions without the capability can't disable the calls + return true; + } + } + return false; + } + + public static boolean isUnifiedSearchAvailable(@Nullable final UserNgEntity user) { + return hasSpreedFeatureCapability(user, "unified-search"); + } +}