updated to 22.0.2

This commit is contained in:
Fr4nz D13trich 2025-10-08 13:14:29 +02:00
parent 7fbf1db963
commit df332bafd8
19 changed files with 75 additions and 175 deletions

View file

@ -13,9 +13,9 @@ import com.github.spotbugs.snom.Effort
import com.github.spotbugs.snom.SpotBugsTask
plugins {
id "org.jetbrains.kotlin.plugin.compose" version "2.2.20"
id "org.jetbrains.kotlin.plugin.compose" version "2.2.10"
id "org.jetbrains.kotlin.kapt"
id 'com.google.devtools.ksp' version '2.2.20-2.0.3'
id 'com.google.devtools.ksp' version '2.2.10-2.0.2'
}
apply plugin: 'com.android.application'
@ -39,8 +39,8 @@ android {
// mayor.minor.hotfix.increment (for increment: 01-50=Alpha / 51-89=RC / 90-99=stable)
// xx .xxx .xx .xx
versionCode 230000009
versionName "23.0.0 Alpha 09"
versionCode 220000290
versionName "22.0.2"
flavorDimensions "default"
renderscriptTargetApi = 19
@ -156,20 +156,20 @@ kapt {
}
ext {
androidxCameraVersion = "1.5.0"
androidxCameraVersion = "1.4.2"
coilKtVersion = "2.7.0"
daggerVersion = "2.57.2"
emojiVersion = "1.6.0"
daggerVersion = "2.57.1"
emojiVersion = "1.5.0"
fidoVersion = "4.1.0-patch2"
lifecycleVersion = '2.9.4'
lifecycleVersion = '2.9.3'
okhttpVersion = "4.12.0"
markwonVersion = "4.6.2"
materialDialogsVersion = "3.3.0"
parcelerVersion = "1.1.13"
prismVersion = "2.0.0"
retrofit2Version = "3.0.0"
roomVersion = "2.8.0"
workVersion = "2.10.5"
roomVersion = "2.7.2"
workVersion = "2.10.3"
espressoVersion = "3.7.0"
androidxTestVersion = "1.5.0"
media3_version = "1.8.0"
@ -186,12 +186,12 @@ configurations.configureEach {
dependencies {
implementation "androidx.room:room-testing-android:${roomVersion}"
implementation 'androidx.compose.foundation:foundation-layout:1.9.2'
implementation 'androidx.compose.foundation:foundation-layout:1.9.0'
spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.14.0'
spotbugsPlugins 'com.mebigfatguy.fb-contrib:fb-contrib:7.6.14'
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:1.23.8")
implementation("androidx.compose.runtime:runtime:1.9.2")
implementation("androidx.compose.runtime:runtime:1.9.0")
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.datastore:datastore-core:1.1.7'
implementation 'androidx.datastore:datastore-preferences:1.1.7'
@ -289,7 +289,7 @@ dependencies {
implementation "com.afollestad.material-dialogs:bottomsheets:${materialDialogsVersion}"
implementation "com.afollestad.material-dialogs:lifecycle:${materialDialogsVersion}"
implementation 'com.google.code.gson:gson:2.13.2'
implementation 'com.google.code.gson:gson:2.13.1'
implementation "androidx.media3:media3-exoplayer:$media3_version"
implementation "androidx.media3:media3-ui:$media3_version"
@ -315,11 +315,11 @@ dependencies {
implementation 'com.github.nextcloud.android-common:ui:0.28.0'
implementation 'com.github.nextcloud-deps:android-talk-webrtc:132.6834.0'
gplayImplementation 'com.google.android.gms:play-services-base:18.8.0'
gplayImplementation "com.google.firebase:firebase-messaging:25.0.1"
gplayImplementation 'com.google.android.gms:play-services-base:18.6.0'
gplayImplementation "com.google.firebase:firebase-messaging:24.1.2"
//compose
implementation(platform("androidx.compose:compose-bom:2025.09.00"))
implementation(platform("androidx.compose:compose-bom:2025.08.01"))
implementation("androidx.compose.ui:ui")
implementation 'androidx.compose.material3:material3:1.3.2'
implementation("androidx.compose.ui:ui-tooling-preview")
@ -328,18 +328,18 @@ dependencies {
//tests
testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.13.4'
androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.9.2")
androidTestImplementation("androidx.compose.ui:ui-test-junit4:1.9.0")
debugImplementation("androidx.compose.ui:ui-test-manifest")
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.mockito:mockito-core:5.20.0'
testImplementation 'org.mockito:mockito-core:5.19.0'
testImplementation 'androidx.arch.core:core-testing:2.2.0'
androidTestImplementation "androidx.test:core:1.7.0"
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.2"
androidTestImplementation 'androidx.test:core-ktx:1.7.0'
androidTestImplementation 'org.mockito:mockito-android:5.20.0'
androidTestImplementation 'org.mockito:mockito-android:5.19.0'
androidTestImplementation "androidx.work:work-testing:${workVersion}"
// Espresso core
androidTestImplementation ("androidx.test.espresso:espresso-core:$espressoVersion", {
@ -353,14 +353,14 @@ dependencies {
androidTestImplementation('com.android.support.test.espresso:espresso-intents:3.0.2')
androidTestImplementation(platform("androidx.compose:compose-bom:2025.09.00"))
androidTestImplementation(platform("androidx.compose:compose-bom:2025.08.01"))
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
testImplementation 'org.junit.vintage:junit-vintage-engine:5.13.4' // DO NOT REMOVE
testImplementation "androidx.room:room-testing:${roomVersion}"
testImplementation("com.squareup.okhttp3:mockwebserver:$okhttpVersion")
testImplementation("com.google.dagger:hilt-android-testing:2.57.2")
testImplementation("com.google.dagger:hilt-android-testing:2.57.1")
testImplementation("org.robolectric:robolectric:4.16")
}

View file

@ -532,12 +532,12 @@ class CallActivity : CallBaseActivity() {
)
}
when (CapabilitiesUtil.getRecordingConsentType(conversationUser!!.capabilities!!.spreedCapability!!)) {
when (CapabilitiesUtil.getRecordingConsentType(conversationUser.capabilities!!.spreedCapability!!)) {
CapabilitiesUtil.RECORDING_CONSENT_NOT_REQUIRED -> initiateCall()
CapabilitiesUtil.RECORDING_CONSENT_REQUIRED -> askForRecordingConsent()
CapabilitiesUtil.RECORDING_CONSENT_DEPEND_ON_CONVERSATION -> {
val getRoomApiVersion = ApiUtils.getConversationApiVersion(
conversationUser!!,
conversationUser,
intArrayOf(ApiUtils.API_V4, 1)
)
ncApi!!.getRoom(credentials, ApiUtils.getUrlForRoom(getRoomApiVersion, baseUrl, roomToken))

View file

@ -3255,7 +3255,8 @@ class ChatActivity :
}
val searchItem = menu.findItem(R.id.conversation_search)
searchItem.isVisible = CapabilitiesUtil.isUnifiedSearchAvailable(spreedCapabilities) &&
searchItem.isVisible =
hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.UNIFIED_SEARCH) &&
currentConversation!!.remoteServer.isNullOrEmpty() &&
!isChatThread()

View file

@ -60,7 +60,7 @@ class ContextChatViewModel @Inject constructor(private val chatNetworkDataSource
token = token,
messageId = messageId,
limit = LIMIT,
threadId = threadId?.toInt()
threadId = threadId?.toIntOrNull()
)
if (threadId.isNullOrEmpty()) {

View file

@ -89,6 +89,8 @@ import com.nextcloud.talk.contacts.ContactsActivity
import com.nextcloud.talk.contacts.ContactsUiState
import com.nextcloud.talk.contacts.ContactsViewModel
import com.nextcloud.talk.contacts.RoomUiState
import com.nextcloud.talk.contextchat.ContextChatView
import com.nextcloud.talk.contextchat.ContextChatViewModel
import com.nextcloud.talk.conversationlist.viewmodels.ConversationsListViewModel
import com.nextcloud.talk.data.network.NetworkMonitor
import com.nextcloud.talk.data.user.model.User
@ -113,8 +115,6 @@ import com.nextcloud.talk.threadsoverview.ThreadsOverviewActivity
import com.nextcloud.talk.ui.BackgroundVoiceMessageCard
import com.nextcloud.talk.ui.dialog.ChooseAccountDialogFragment
import com.nextcloud.talk.ui.dialog.ChooseAccountShareToDialogFragment
import com.nextcloud.talk.contextchat.ContextChatView
import com.nextcloud.talk.contextchat.ContextChatViewModel
import com.nextcloud.talk.ui.dialog.ConversationsListBottomDialog
import com.nextcloud.talk.ui.dialog.FilterConversationFragment
import com.nextcloud.talk.ui.dialog.FilterConversationFragment.Companion.ARCHIVE
@ -125,7 +125,6 @@ import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.BrandingUtils
import com.nextcloud.talk.utils.CapabilitiesUtil.hasSpreedFeatureCapability
import com.nextcloud.talk.utils.CapabilitiesUtil.isServerEOL
import com.nextcloud.talk.utils.CapabilitiesUtil.isUnifiedSearchAvailable
import com.nextcloud.talk.utils.ClosedInterfaceImpl
import com.nextcloud.talk.utils.ConversationUtils
import com.nextcloud.talk.utils.FileUtils
@ -319,7 +318,7 @@ class ConversationsListActivity :
return
}
currentUser?.capabilities?.spreedCapability?.let { spreedCapabilities ->
if (isUnifiedSearchAvailable(spreedCapabilities)) {
if (hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.UNIFIED_SEARCH)) {
searchHelper = MessageSearchHelper(unifiedSearchRepository)
}
}
@ -1072,7 +1071,7 @@ class ConversationsListActivity :
}
private fun fetchPendingInvitations() {
if (hasSpreedFeatureCapability(currentUser!!.capabilities!!.spreedCapability!!, SpreedFeatures.FEDERATION_V1)) {
if (hasSpreedFeatureCapability(currentUser?.capabilities?.spreedCapability, SpreedFeatures.FEDERATION_V1)) {
binding.conversationListHintInclude.conversationListHintLayout.setOnClickListener {
val intent = Intent(this, InvitationsActivity::class.java)
startActivity(intent)
@ -1203,7 +1202,7 @@ class ConversationsListActivity :
searchableConversationItems.clear()
searchableConversationItems.addAll(conversationItemsWithHeader)
if (hasSpreedFeatureCapability(
currentUser!!.capabilities!!.spreedCapability!!,
currentUser?.capabilities?.spreedCapability,
SpreedFeatures.LISTABLE_ROOMS
)
) {
@ -1464,7 +1463,11 @@ class ConversationsListActivity :
adapter?.filterItems()
}
if (isUnifiedSearchAvailable(currentUser!!.capabilities!!.spreedCapability!!)) {
if (hasSpreedFeatureCapability(
currentUser?.capabilities?.spreedCapability,
SpreedFeatures.UNIFIED_SEARCH
)
) {
startMessageSearch(filter)
}
} else {
@ -1584,7 +1587,7 @@ class ConversationsListActivity :
selectedConversation = conversation
if (selectedConversation != null) {
val hasChatPermission = ParticipantPermissions(
currentUser!!.capabilities!!.spreedCapability!!,
currentUser?.capabilities?.spreedCapability,
selectedConversation!!
)
.hasChatPermission()
@ -1612,11 +1615,11 @@ class ConversationsListActivity :
private fun shouldShowLobby(conversation: ConversationModel): Boolean {
val participantPermissions = ParticipantPermissions(
currentUser!!.capabilities?.spreedCapability!!,
currentUser?.capabilities?.spreedCapability,
selectedConversation!!
)
return conversation.lobbyState == ConversationEnums.LobbyState.LOBBY_STATE_MODERATORS_ONLY &&
!ConversationUtils.canModerate(conversation, currentUser!!.capabilities!!.spreedCapability!!) &&
!ConversationUtils.canModerate(conversation, currentUser?.capabilities?.spreedCapability) &&
!participantPermissions.canIgnoreLobby()
}

View file

@ -232,7 +232,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
bundle.putInt(BundleKeys.KEY_CALL_FLAG, conversation.callFlag)
val participantPermission = ParticipantPermissions(
userBeingCalled!!.capabilities!!.spreedCapability!!,
userBeingCalled?.capabilities?.spreedCapability,
conversation
)
bundle.putBoolean(

View file

@ -244,7 +244,7 @@ class ProfileActivity : BaseActivity() {
binding.emptyList.root.visibility = View.GONE
binding.userinfoList.visibility = View.VISIBLE
if (CapabilitiesUtil.hasSpreedFeatureCapability(
currentUser!!.capabilities!!.spreedCapability!!,
currentUser?.capabilities?.spreedCapability,
SpreedFeatures.TEMP_USER_AVATAR_API
)
) {

View file

@ -945,7 +945,7 @@ class SettingsActivity :
binding.settingsShowNotificationWarning.visibility = View.GONE
}
if (CapabilitiesUtil.isReadStatusAvailable(currentUser!!.capabilities!!.spreedCapability!!)) {
if (CapabilitiesUtil.isReadStatusAvailable(currentUser?.capabilities?.spreedCapability)) {
binding.settingsReadPrivacySwitch.isChecked = !CapabilitiesUtil.isReadStatusPrivate(currentUser!!)
} else {
binding.settingsReadPrivacy.visibility = View.GONE

View file

@ -100,11 +100,13 @@ object CapabilitiesUtil {
//region SpreedCapabilities
@JvmStatic
fun hasSpreedFeatureCapability(spreedCapabilities: SpreedCapability, spreedFeatures: SpreedFeatures): Boolean {
if (spreedCapabilities.features != null) {
return spreedCapabilities.features!!.contains(spreedFeatures.value)
fun hasSpreedFeatureCapability(spreedCapabilities: SpreedCapability?, spreedFeatures: SpreedFeatures): Boolean {
if (spreedCapabilities == null) {
Log.e(TAG, "spreedCapabilities were null when checking capability ${spreedFeatures.value}")
return false
}
return false
return spreedCapabilities.features?.contains(spreedFeatures.value) == true
}
fun isSharedItemsAvailable(spreedCapabilities: SpreedCapability): Boolean =
@ -136,12 +138,16 @@ object CapabilitiesUtil {
return CONVERSATION_DESCRIPTION_LENGTH_FOR_OLD_SERVER
}
fun isReadStatusAvailable(spreedCapabilities: SpreedCapability): Boolean {
if (spreedCapabilities.config?.containsKey("chat") == true) {
val map: Map<String, Any>? = spreedCapabilities.config!!["chat"]
return map != null && map.containsKey("read-privacy")
fun isReadStatusAvailable(spreedCapabilities: SpreedCapability?): Boolean {
val chatConfig = spreedCapabilities?.config?.get("chat") as? Map<*, *>
return if (chatConfig?.containsKey("read-privacy") == true) {
true
} else {
if (spreedCapabilities == null) {
Log.e(TAG, "spreedCapabilities were null when checking capability isReadStatusAvailable")
}
false
}
return false
}
fun retentionOfEventRooms(spreedCapabilities: SpreedCapability): Int {
@ -201,9 +207,6 @@ object CapabilitiesUtil {
fun isConversationDescriptionEndpointAvailable(spreedCapabilities: SpreedCapability): Boolean =
hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.ROOM_DESCRIPTION)
fun isUnifiedSearchAvailable(spreedCapabilities: SpreedCapability): Boolean =
hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.UNIFIED_SEARCH)
fun isAbleToCall(spreedCapabilities: SpreedCapability): Boolean =
if (
spreedCapabilities.config?.containsKey("call") == true &&

View file

@ -27,11 +27,11 @@ object ConversationUtils {
Participant.ParticipantType.GUEST_MODERATOR == conversation.participantType ||
Participant.ParticipantType.MODERATOR == conversation.participantType
fun isLockedOneToOne(conversation: ConversationModel, spreedCapabilities: SpreedCapability): Boolean =
fun isLockedOneToOne(conversation: ConversationModel, spreedCapabilities: SpreedCapability?): Boolean =
conversation.type == ConversationEnums.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL &&
CapabilitiesUtil.hasSpreedFeatureCapability(spreedCapabilities, SpreedFeatures.LOCKED_ONE_TO_ONE)
fun canModerate(conversation: ConversationModel, spreedCapabilities: SpreedCapability): Boolean =
fun canModerate(conversation: ConversationModel, spreedCapabilities: SpreedCapability?): Boolean =
isParticipantOwnerOrModerator(conversation) &&
!isLockedOneToOne(conversation, spreedCapabilities) &&
conversation.type != ConversationEnums.ConversationType.FORMER_ONE_TO_ONE &&

View file

@ -14,7 +14,7 @@ import com.nextcloud.talk.models.json.capabilities.SpreedCapability
* see https://nextcloud-talk.readthedocs.io/en/latest/constants/#attendee-permissions
*/
class ParticipantPermissions(
private val spreedCapabilities: SpreedCapability,
private val spreedCapabilities: SpreedCapability?,
private val conversation: ConversationModel
) {
val isDefault = (conversation.permissions and DEFAULT) == DEFAULT

View file

@ -565,6 +565,7 @@
<string name="shared_items_voice">音声番号</string>
<string name="starred">お気に入り</string>
<string name="startCallForbidden">通話を開始することが許可されていません</string>
<string name="start_thread">スレッドを作成する</string>
<string name="started_a_call">会話を開始</string>
<string name="status_message">ステータスメッセージ</string>
<string name="switch_to_breakout_room">ブレイクアウトルームに切り替える</string>

View file

@ -83,7 +83,7 @@
<string name="location_permission_denied_msg">Por favor, ative-a nas configurações do aplicativo</string>
<string name="location_services_disabled">Serviços de localização desativados</string>
<string name="location_services_disabled_msg">Ative os serviços de localização (GPS) para usar este recurso</string>
<string name="lock_conversation">Bloquear conversa</string>
<string name="lock_conversation">Trancar conversa</string>
<string name="lock_symbol">Símbolo de cadeado</string>
<string name="lower_hand">Baixar mão</string>
<string name="marked_as_read">Conversa %1$s marcada como lida</string>
@ -118,7 +118,7 @@
<string name="nc_add_to_favorites">Adicionar aos favoritos</string>
<string name="nc_all_ok_operation">OK, tudo pronto!</string>
<string name="nc_attendee_pin">PIN: %1$s</string>
<string name="nc_biometric_unlock">Desbloquear %1$s</string>
<string name="nc_biometric_unlock">Destrancar %1$s</string>
<string name="nc_bluetooth_permission_hint">Para ativar os alto-falantes bluetooth, conceda a permissão \"Dispositivos próximos\".</string>
<string name="nc_call_button_content_description_answer_video_call">Atender como chamada de vídeo</string>
<string name="nc_call_button_content_description_answer_voice_only">Atender apenas como chamada de voz</string>
@ -316,8 +316,8 @@
<string name="nc_location_current_position_description">Sua localização atual</string>
<string name="nc_location_permission_required">permissão de localização é necessária</string>
<string name="nc_location_unknown">Posição desconhecida</string>
<string name="nc_locked">Bloqueado</string>
<string name="nc_locked_tap_to_unlock">Toque para desbloquear</string>
<string name="nc_locked">Trancado</string>
<string name="nc_locked_tap_to_unlock">Toque para destrancar</string>
<string name="nc_manual">Não definido</string>
<string name="nc_mark_as_read">Marcar como lido</string>
<string name="nc_mark_as_unread">Marcar como não lido</string>
@ -484,9 +484,9 @@
<string name="nc_settings_remove">Excluir</string>
<string name="nc_settings_remove_account">Excluir conta</string>
<string name="nc_settings_remove_confirmation">Confirme se quer realmente excluir a conta atual.</string>
<string name="nc_settings_screen_lock_desc">Bloquear %1$s com o bloqueio de tela do Android ou um método biométrico suportado</string>
<string name="nc_settings_screen_lock_desc">Trancar %1$s com o bloqueio de tela do Android ou um método biométrico suportado</string>
<string name="nc_settings_screen_lock_timeout_title">Tempo limite para bloqueio de tela</string>
<string name="nc_settings_screen_lock_title">Bloquear tela</string>
<string name="nc_settings_screen_lock_title">Bloqueio de tela</string>
<string name="nc_settings_screen_security_desc">Impede capturas de tela na lista recente e dentro do aplicativo</string>
<string name="nc_settings_screen_security_title">Segurança da tela</string>
<string name="nc_settings_server_almost_eol">A versão do servidor é muito antiga e não será suportada na próxima versão!</string>