This commit is contained in:
Marcel Hibbe 2025-06-18 18:52:49 +02:00 committed by GitHub
commit 94bbc5ec0a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 606 additions and 349 deletions

View File

@ -28,13 +28,13 @@ apply plugin: "org.jlleitschuh.gradle.ktlint"
apply plugin: 'kotlinx-serialization' apply plugin: 'kotlinx-serialization'
android { android {
compileSdk 34 compileSdk 35
namespace 'com.nextcloud.talk' namespace 'com.nextcloud.talk'
defaultConfig { defaultConfig {
minSdkVersion 26 minSdkVersion 26
targetSdkVersion 34 targetSdkVersion 35
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
// mayor.minor.hotfix.increment (for increment: 01-50=Alpha / 51-89=RC / 90-99=stable) // mayor.minor.hotfix.increment (for increment: 01-50=Alpha / 51-89=RC / 90-99=stable)
@ -303,7 +303,7 @@ dependencies {
implementation 'androidx.core:core-ktx:1.13.1' implementation 'androidx.core:core-ktx:1.13.1'
implementation 'androidx.activity:activity-ktx:1.9.3' implementation 'androidx.activity:activity-ktx:1.9.3'
implementation 'com.github.nextcloud.android-common:ui:0.23.2' implementation 'com.github.nextcloud.android-common:ui:0.26.0'
implementation 'com.github.nextcloud-deps:android-talk-webrtc:132.6834.0' implementation 'com.github.nextcloud-deps:android-talk-webrtc:132.6834.0'
gplayImplementation 'com.google.android.gms:play-services-base:18.6.0' gplayImplementation 'com.google.android.gms:play-services-base:18.6.0'

View File

@ -91,7 +91,7 @@ class AccountVerificationActivity : BaseActivity() {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
setContentView(binding.root) setContentView(binding.root)
actionBar?.hide() actionBar?.hide()
setupSystemColors() initSystemBars()
handleIntent() handleIntent()
} }

View File

@ -78,7 +78,7 @@ class ServerSelectionActivity : BaseActivity() {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
setContentView(binding.root) setContentView(binding.root)
actionBar?.hide() actionBar?.hide()
setupSystemColors() initSystemBars()
onBackPressedDispatcher.addCallback(this, onBackPressedCallback) onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
} }

View File

@ -86,7 +86,7 @@ class SwitchAccountActivity : BaseActivity() {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
setContentView(binding.root) setContentView(binding.root)
setupActionBar() setupActionBar()
setupSystemColors() initSystemBars()
Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context)) Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context))

View File

@ -114,7 +114,7 @@ class WebViewLoginActivity : BaseActivity() {
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
setContentView(binding.root) setContentView(binding.root)
actionBar?.hide() actionBar?.hide()
setupSystemColors() initSystemBars()
onBackPressedDispatcher.addCallback(this, onBackPressedCallback) onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
handleIntent() handleIntent()

View File

@ -11,11 +11,13 @@ package com.nextcloud.talk.activities
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.text.TextUtils import android.text.TextUtils
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.WindowInsets
import android.view.WindowManager import android.view.WindowManager
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.webkit.SslErrorHandler import android.webkit.SslErrorHandler
@ -37,6 +39,7 @@ import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.FileViewerUtils import com.nextcloud.talk.utils.FileViewerUtils
import com.nextcloud.talk.utils.UriUtils import com.nextcloud.talk.utils.UriUtils
import com.nextcloud.talk.utils.adjustUIForAPILevel35
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.preferences.AppPreferences
@ -81,6 +84,7 @@ open class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
adjustUIForAPILevel35()
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
cleanTempCertPreference() cleanTempCertPreference()
@ -111,10 +115,23 @@ open class BaseActivity : AppCompatActivity() {
eventBus.unregister(this) eventBus.unregister(this)
} }
fun setupSystemColors() { /*
* May be aligned with android-common lib in the future: .../ui/util/extensions/AppCompatActivityExtensions.kt
*/
fun initSystemBars() {
window.decorView.setOnApplyWindowInsetsListener { view, insets ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
val statusBarHeight = insets.getInsets(WindowInsets.Type.statusBars()).top
view.setPadding(0, statusBarHeight, 0, 0)
val color = ResourcesCompat.getColor(resources, R.color.bg_default, context.theme)
view.setBackgroundColor(color)
} else {
colorizeStatusBar() colorizeStatusBar()
colorizeNavigationBar() colorizeNavigationBar()
} }
insets
}
}
open fun colorizeStatusBar() { open fun colorizeStatusBar() {
if (resources != null) { if (resources != null) {

View File

@ -0,0 +1,41 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.adapters.items
import android.view.View
import com.nextcloud.talk.R
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder
class SpacerItem(private val height: Int) : AbstractFlexibleItem<SpacerItem.ViewHolder>() {
override fun getLayoutRes(): Int = R.layout.item_spacer
override fun createViewHolder(view: View?, adapter: FlexibleAdapter<IFlexible<*>?>?): ViewHolder {
return ViewHolder(view!!, adapter!!)
}
override fun bindViewHolder(
adapter: FlexibleAdapter<IFlexible<*>?>?,
holder: ViewHolder,
position: Int,
payloads: MutableList<Any>?
) {
holder.itemView.layoutParams.height = height
}
override fun equals(other: Any?) = other is SpacerItem
override fun hashCode(): Int {
return 0
}
class ViewHolder(view: View, adapter: FlexibleAdapter<*>) :
FlexibleViewHolder(view, adapter)
}

View File

@ -66,6 +66,8 @@ import androidx.core.graphics.drawable.toDrawable
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.core.text.bold import androidx.core.text.bold
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.emoji2.text.EmojiCompat import androidx.emoji2.text.EmojiCompat
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.fragment.app.commit import androidx.fragment.app.commit
@ -458,7 +460,28 @@ class ChatActivity :
binding = ActivityChatBinding.inflate(layoutInflater) binding = ActivityChatBinding.inflate(layoutInflater)
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.chat_container)) { view, insets ->
val statusBarInsets = insets.getInsets(WindowInsetsCompat.Type.statusBars())
val navBarInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars())
val imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime())
val isKeyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
val bottomPadding = if (isKeyboardVisible) imeInsets.bottom else navBarInsets.bottom
view.setPadding(
view.paddingLeft,
statusBarInsets.top,
view.paddingRight,
bottomPadding
)
WindowInsetsCompat.CONSUMED
}
} else {
colorizeStatusBar()
colorizeNavigationBar()
}
conversationUser = currentUserProvider.currentUser.blockingGet() conversationUser = currentUserProvider.currentUser.blockingGet()
handleIntent(intent) handleIntent(intent)
@ -486,7 +509,7 @@ class ChatActivity :
initObservers() initObservers()
pickMultipleMedia = registerForActivityResult( pickMultipleMedia = registerForActivityResult(
ActivityResultContracts.PickMultipleVisualMedia(5) ActivityResultContracts.PickMultipleVisualMedia(MAX_AMOUNT_MEDIA_FILE_PICKER)
) { uris -> ) { uris ->
if (uris.isNotEmpty()) { if (uris.isNotEmpty()) {
onChooseFileResult(uris) onChooseFileResult(uris)
@ -684,7 +707,7 @@ class ChatActivity :
?.split("#") ?.split("#")
?.getOrNull(1) ?.getOrNull(1)
?.toLongOrNull() ?.toLongOrNull()
val currentTimeStamp = (System.currentTimeMillis() / 1000).toLong() val currentTimeStamp = (System.currentTimeMillis() / ONE_SECOND_IN_MILLIS).toLong()
val retentionPeriod = retentionOfEventRooms(spreedCapabilities) val retentionPeriod = retentionOfEventRooms(spreedCapabilities)
val isPastEvent = eventEndTimeStamp?.let { it < currentTimeStamp } val isPastEvent = eventEndTimeStamp?.let { it < currentTimeStamp }
if (isPastEvent == true && retentionPeriod != 0) { if (isPastEvent == true && retentionPeriod != 0) {
@ -4193,5 +4216,6 @@ class ChatActivity :
const val OUT_OF_OFFICE_ALPHA = 76 const val OUT_OF_OFFICE_ALPHA = 76
const val ZERO_INDEX = 0 const val ZERO_INDEX = 0
const val ONE_INDEX = 1 const val ONE_INDEX = 1
const val MAX_AMOUNT_MEDIA_FILE_PICKER = 10
} }
} }

View File

@ -1,7 +1,6 @@
/* /*
* Nextcloud Talk - Android Client * Nextcloud Talk - Android Client
* *
* SPDX-FileCopyrightText: 2024 Sowjanya Kota <sowjanya.kch@gmail.com>
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de> * SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
* SPDX-License-Identifier: GPL-3.0-or-later * SPDX-License-Identifier: GPL-3.0-or-later
*/ */
@ -9,16 +8,41 @@
package com.nextcloud.talk.components package com.nextcloud.talk.components
import android.app.Activity import android.app.Activity
import android.os.Build
import androidx.compose.foundation.background
import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.windowInsetsTopHeight
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalView import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
@Composable @Composable
fun SetupSystemBars() { fun ColoredStatusBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
Box(modifier = Modifier.fillMaxSize()) {
Box(
Modifier
.windowInsetsTopHeight(WindowInsets.statusBars)
.fillMaxWidth()
.background(MaterialTheme.colorScheme.surface)
)
}
} else {
ColorLegacyStatusBar()
}
}
@Composable
private fun ColorLegacyStatusBar() {
val view = LocalView.current val view = LocalView.current
val isDarkMode = isSystemInDarkTheme() val isDarkMode = isSystemInDarkTheme()
val statusBarColor = MaterialTheme.colorScheme.surface.toArgb() val statusBarColor = MaterialTheme.colorScheme.surface.toArgb()

View File

@ -0,0 +1,24 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.components
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@Composable
fun VerticallyCenteredRow(content: @Composable RowScope.() -> Unit) {
Row(
modifier = Modifier.fillMaxHeight(),
verticalAlignment = Alignment.CenterVertically,
content = content
)
}

View File

@ -18,9 +18,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import autodagger.AutoInjector import autodagger.AutoInjector
import com.nextcloud.talk.activities.BaseActivity import com.nextcloud.talk.activities.BaseActivity
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.components.ColoredStatusBar
import com.nextcloud.talk.contacts.CompanionClass.Companion.KEY_HIDE_ALREADY_EXISTING_PARTICIPANTS import com.nextcloud.talk.contacts.CompanionClass.Companion.KEY_HIDE_ALREADY_EXISTING_PARTICIPANTS
import com.nextcloud.talk.extensions.getParcelableArrayListExtraProvider import com.nextcloud.talk.extensions.getParcelableArrayListExtraProvider
import com.nextcloud.talk.components.SetupSystemBars
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
import javax.inject.Inject import javax.inject.Inject
@ -64,11 +64,11 @@ class ContactsActivity : BaseActivity() {
MaterialTheme( MaterialTheme(
colorScheme = colorScheme colorScheme = colorScheme
) { ) {
ColoredStatusBar()
ContactsScreen( ContactsScreen(
contactsViewModel = contactsViewModel, contactsViewModel = contactsViewModel,
uiState = uiState.value uiState = uiState.value
) )
SetupSystemBars()
} }
} }
} }

View File

@ -11,16 +11,18 @@ package com.nextcloud.talk.contacts
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.contacts.components.AppBar import com.nextcloud.talk.contacts.components.ContactsAppBar
import com.nextcloud.talk.contacts.components.ContactsList import com.nextcloud.talk.contacts.components.ContactsList
import com.nextcloud.talk.contacts.components.ContactsSearchAppBar
import com.nextcloud.talk.contacts.components.ConversationCreationOptions import com.nextcloud.talk.contacts.components.ConversationCreationOptions
@Composable @Composable
@ -32,35 +34,37 @@ fun ContactsScreen(contactsViewModel: ContactsViewModel, uiState: ContactsUiStat
val enableAddButton by contactsViewModel.enableAddButton.collectAsStateWithLifecycle() val enableAddButton by contactsViewModel.enableAddButton.collectAsStateWithLifecycle()
Scaffold( Scaffold(
modifier = Modifier
.statusBarsPadding(),
topBar = { topBar = {
AppBar( if (isSearchActive) {
title = stringResource(R.string.nc_app_product_name), ContactsSearchAppBar(
searchQuery = searchQuery, searchQuery = searchQuery,
isSearchActive = isSearchActive, onTextChange = {
isAddParticipants = isAddParticipants, contactsViewModel.updateSearchQuery(it)
autocompleteUsers = autocompleteUsers, contactsViewModel.getContactsFromSearchParams()
onEnableSearch = {
contactsViewModel.setSearchActive(true)
}, },
onDisableSearch = { onCloseSearch = {
contactsViewModel.updateSearchQuery("")
contactsViewModel.setSearchActive(false) contactsViewModel.setSearchActive(false)
},
onUpdateSearchQuery = {
contactsViewModel.updateSearchQuery(query = it)
},
onUpdateAutocompleteUsers = {
contactsViewModel.getContactsFromSearchParams() contactsViewModel.getContactsFromSearchParams()
}, },
enableAddButton = enableAddButton, enableAddButton = enableAddButton,
clickAddButton = { isAddParticipants = isAddParticipants,
contactsViewModel.modifyClickAddButton(it) clickAddButton = { contactsViewModel.modifyClickAddButton(true) }
}
) )
} else {
ContactsAppBar(
isAddParticipants = isAddParticipants,
autocompleteUsers = autocompleteUsers,
onStartSearch = { contactsViewModel.setSearchActive(true) }
)
}
}, },
content = { content = { paddingValues ->
Column( Column(
Modifier Modifier
.padding(it) .padding(0.dp, paddingValues.calculateTopPadding(), 0.dp, 0.dp)
.background(colorResource(id = R.color.bg_default)) .background(colorResource(id = R.color.bg_default))
) { ) {
if (!isAddParticipants) { if (!isAddParticipants) {

View File

@ -1,117 +0,0 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2024 Sowjanya Kota <sowjanya.kch@gmail.com>
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.contacts.components
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import com.nextcloud.talk.R
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
@SuppressLint("UnrememberedMutableState")
@OptIn(ExperimentalMaterial3Api::class)
@Suppress("LongParameterList", "LongMethod")
@Composable
fun AppBar(
title: String,
searchQuery: String,
isSearchActive: Boolean,
isAddParticipants: Boolean,
autocompleteUsers: List<AutocompleteUser>,
onEnableSearch: () -> Unit,
onDisableSearch: () -> Unit,
onUpdateSearchQuery: (String) -> Unit,
onUpdateAutocompleteUsers: () -> Unit,
enableAddButton: Boolean,
clickAddButton: (Boolean) -> Unit
) {
val context = LocalContext.current
val appTitle = if (!isSearchActive) {
title
} else {
""
}
TopAppBar(
title = { Text(text = appTitle) },
navigationIcon = {
IconButton(onClick = {
(context as? Activity)?.finish()
}) {
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(R.string.back_button))
}
},
actions = {
if (!isSearchActive) {
IconButton(onClick = onEnableSearch) {
Icon(Icons.Filled.Search, contentDescription = stringResource(R.string.search_icon))
}
if (isAddParticipants) {
Text(
text = stringResource(id = R.string.nc_contacts_done),
modifier = Modifier.clickable {
val resultIntent = Intent().apply {
putParcelableArrayListExtra(
"selectedParticipants",
ArrayList(autocompleteUsers)
)
}
(context as? Activity)?.setResult(Activity.RESULT_OK, resultIntent)
(context as? Activity)?.finish()
}
)
}
}
}
)
if (isSearchActive) {
Row(modifier = Modifier.fillMaxWidth()) {
SearchComponent(
text = searchQuery,
onTextChange = { searchQuery ->
onUpdateSearchQuery(searchQuery)
onUpdateAutocompleteUsers()
},
onDisableSearch = onDisableSearch,
modifier = Modifier.weight(1f)
)
if (isAddParticipants) {
TextButton(
modifier = Modifier.align(Alignment.CenterVertically).wrapContentWidth(),
onClick = {
onDisableSearch()
onUpdateSearchQuery("")
clickAddButton(true)
onUpdateAutocompleteUsers()
},
enabled = enableAddButton
) {
Text(text = context.getString(R.string.add_participants))
}
}
}
}
}

View File

@ -0,0 +1,77 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2024 Sowjanya Kota <sowjanya.kch@gmail.com>
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.contacts.components
import android.app.Activity
import android.content.Intent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.height
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.nextcloud.talk.R
import com.nextcloud.talk.components.VerticallyCenteredRow
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ContactsAppBar(isAddParticipants: Boolean, autocompleteUsers: List<AutocompleteUser>, onStartSearch: () -> Unit) {
val context = LocalContext.current
TopAppBar(
modifier = Modifier
.height(60.dp),
title = {
VerticallyCenteredRow {
Text(
text = if (isAddParticipants) {
stringResource(R.string.nc_participants_add)
} else {
stringResource(R.string.nc_new_conversation)
}
)
}
},
navigationIcon = {
VerticallyCenteredRow {
IconButton(onClick = { (context as? Activity)?.finish() }) {
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(R.string.back_button))
}
}
},
actions = {
VerticallyCenteredRow {
IconButton(onClick = onStartSearch) {
Icon(Icons.Filled.Search, contentDescription = stringResource(R.string.search_icon))
}
if (isAddParticipants) {
Text(
text = stringResource(id = R.string.nc_contacts_done),
modifier = Modifier.clickable {
val resultIntent = Intent().apply {
putParcelableArrayListExtra("selectedParticipants", ArrayList(autocompleteUsers))
}
(context as? Activity)?.setResult(Activity.RESULT_OK, resultIntent)
(context as? Activity)?.finish()
}
)
}
}
}
)
}

View File

@ -15,7 +15,6 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
@ -44,9 +43,13 @@ fun ContactsItem(contacts: List<AutocompleteUser>, contactsViewModel: ContactsVi
} }
LazyColumn( LazyColumn(
modifier = Modifier modifier = Modifier
.padding(8.dp)
.fillMaxWidth(), .fillMaxWidth(),
contentPadding = PaddingValues(all = 10.dp), contentPadding = PaddingValues(
top = 10.dp,
bottom = 40.dp,
start = 10.dp,
end = 10.dp
),
verticalArrangement = Arrangement.spacedBy(10.dp) verticalArrangement = Arrangement.spacedBy(10.dp)
) { ) {
groupedContacts.forEach { (initial, contactsForInitial) -> groupedContacts.forEach { (initial, contactsForInitial) ->

View File

@ -0,0 +1,104 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2024 Sowjanya Kota <sowjanya.kch@gmail.com>
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.contacts.components
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.SoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import com.nextcloud.talk.R
import com.nextcloud.talk.components.VerticallyCenteredRow
@Suppress("LongParameterList")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ContactsSearchAppBar(
searchQuery: String,
onTextChange: (String) -> Unit,
onCloseSearch: () -> Unit,
enableAddButton: Boolean,
isAddParticipants: Boolean,
clickAddButton: (Boolean) -> Unit
) {
val keyboardController = LocalSoftwareKeyboardController.current
Surface(
modifier = Modifier.height(60.dp)
) {
VerticallyCenteredRow {
IconButton(
modifier = Modifier
.padding(start = 4.dp),
onClick = onCloseSearch
) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = stringResource(R.string.back_button)
)
}
TextField(
value = searchQuery,
onValueChange = onTextChange,
placeholder = { Text(text = stringResource(R.string.nc_search)) },
singleLine = true,
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
keyboardActions = searchKeyboardActions(searchQuery, keyboardController),
colors = searchTextFieldColors()
)
if (isAddParticipants) {
TextButton(
onClick = {
onCloseSearch()
clickAddButton(true)
},
enabled = enableAddButton
) {
Text(text = stringResource(R.string.add_participants))
}
}
}
}
}
@Composable
fun searchTextFieldColors() =
TextFieldDefaults.colors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent
)
fun searchKeyboardActions(text: String, keyboardController: SoftwareKeyboardController?) =
KeyboardActions(
onSearch = {
if (text.trim().isNotEmpty()) {
keyboardController?.hide()
}
}
)

View File

@ -1,105 +0,0 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2025 Julius Linus <juliuslinus1@gmail.com>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.contacts.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.SoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.nextcloud.talk.R
@Composable
fun SearchComponent(
text: String,
onTextChange: (String) -> Unit,
onDisableSearch: () -> Unit,
modifier: Modifier = Modifier
) {
val keyboardController = LocalSoftwareKeyboardController.current
TextField(
value = text,
onValueChange = { onTextChange(it) },
modifier = modifier
.background(MaterialTheme.colorScheme.background)
.height(60.dp),
placeholder = { Text(text = stringResource(R.string.nc_search)) },
textStyle = TextStyle(fontSize = 16.sp),
singleLine = true,
leadingIcon = { LeadingIcon(onTextChange, onDisableSearch) },
trailingIcon = { TrailingIcon(text, onTextChange) },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
keyboardActions = searchKeyboardActions(text, keyboardController),
colors = searchTextFieldColors(),
maxLines = 1
)
}
@Composable
fun searchTextFieldColors() =
TextFieldDefaults.colors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent
)
@Composable
fun LeadingIcon(onTextChange: (String) -> Unit, onDisableSearch: () -> Unit) {
IconButton(
onClick = {
onTextChange("")
onDisableSearch()
}
) {
Icon(
imageVector = Icons.AutoMirrored.Default.ArrowBack,
contentDescription = stringResource(R.string.back_button)
)
}
}
@Composable
fun TrailingIcon(text: String, onTextChange: (String) -> Unit) {
if (text.isNotEmpty()) {
IconButton(
onClick = { onTextChange("") }
) {
Icon(
imageVector = Icons.Default.Close,
contentDescription = stringResource(R.string.close_icon)
)
}
}
}
fun searchKeyboardActions(text: String, keyboardController: SoftwareKeyboardController?) =
KeyboardActions(
onSearch = {
if (text.trim().isNotEmpty()) {
keyboardController?.hide()
}
}
)

View File

@ -84,8 +84,8 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.activities.BaseActivity import com.nextcloud.talk.activities.BaseActivity
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.chat.ChatActivity import com.nextcloud.talk.chat.ChatActivity
import com.nextcloud.talk.components.ColoredStatusBar
import com.nextcloud.talk.contacts.ContactsActivity import com.nextcloud.talk.contacts.ContactsActivity
import com.nextcloud.talk.components.SetupSystemBars
import com.nextcloud.talk.contacts.loadImage import com.nextcloud.talk.contacts.loadImage
import com.nextcloud.talk.extensions.getParcelableArrayListExtraProvider import com.nextcloud.talk.extensions.getParcelableArrayListExtraProvider
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
@ -117,7 +117,6 @@ class ConversationCreationActivity : BaseActivity() {
colorScheme = colorScheme colorScheme = colorScheme
) { ) {
ConversationCreationScreen(conversationCreationViewModel, context, pickImage) ConversationCreationScreen(conversationCreationViewModel, context, pickImage)
SetupSystemBars()
} }
} }
} }
@ -172,6 +171,7 @@ fun ConversationCreationScreen(
} }
) )
ColoredStatusBar()
Scaffold( Scaffold(
topBar = { topBar = {
TopAppBar( TopAppBar(
@ -191,7 +191,7 @@ fun ConversationCreationScreen(
content = { paddingValues -> content = { paddingValues ->
Column( Column(
modifier = Modifier modifier = Modifier
.padding(paddingValues) .padding(0.dp, paddingValues.calculateTopPadding(), 0.dp, 0.dp)
.background(colorResource(id = R.color.bg_default)) .background(colorResource(id = R.color.bg_default))
.fillMaxSize() .fillMaxSize()
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())

View File

@ -190,7 +190,7 @@ class ConversationInfoActivity :
binding = ActivityConversationInfoBinding.inflate(layoutInflater) binding = ActivityConversationInfoBinding.inflate(layoutInflater)
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors() initSystemBars()
viewModel = viewModel =
ViewModelProvider(this, viewModelFactory)[ConversationInfoViewModel::class.java] ViewModelProvider(this, viewModelFactory)[ConversationInfoViewModel::class.java]

View File

@ -99,7 +99,7 @@ class ConversationInfoEditActivity : BaseActivity() {
binding = ActivityConversationInfoEditBinding.inflate(layoutInflater) binding = ActivityConversationInfoEditBinding.inflate(layoutInflater)
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors() initSystemBars()
val extras: Bundle? = intent.extras val extras: Bundle? = intent.extras

View File

@ -81,6 +81,7 @@ import com.nextcloud.talk.adapters.items.GenericTextHeaderItem
import com.nextcloud.talk.adapters.items.LoadMoreResultsItem import com.nextcloud.talk.adapters.items.LoadMoreResultsItem
import com.nextcloud.talk.adapters.items.MessageResultItem import com.nextcloud.talk.adapters.items.MessageResultItem
import com.nextcloud.talk.adapters.items.MessagesTextHeaderItem import com.nextcloud.talk.adapters.items.MessagesTextHeaderItem
import com.nextcloud.talk.adapters.items.SpacerItem
import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager
@ -266,7 +267,7 @@ class ConversationsListActivity :
binding = ActivityConversationsBinding.inflate(layoutInflater) binding = ActivityConversationsBinding.inflate(layoutInflater)
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors() initSystemBars()
viewThemeUtils.material.themeCardView(binding.searchToolbar) viewThemeUtils.material.themeCardView(binding.searchToolbar)
viewThemeUtils.material.themeSearchBarText(binding.searchText) viewThemeUtils.material.themeSearchBarText(binding.searchText)
@ -293,10 +294,9 @@ class ConversationsListActivity :
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
// actionBar?.show()
if (adapter == null) { if (adapter == null) {
adapter = FlexibleAdapter(conversationItems, this, true) adapter = FlexibleAdapter(conversationItems, this, true)
addEmptyItemForEdgeToEdgeIfNecessary()
} else { } else {
binding.loadingContent.visibility = View.GONE binding.loadingContent.visibility = View.GONE
} }
@ -342,6 +342,14 @@ class ConversationsListActivity :
showSearchOrToolbar() showSearchOrToolbar()
} }
// if edge to edge is used, add an empty item at the bottom of the list
@Suppress("MagicNumber")
private fun addEmptyItemForEdgeToEdgeIfNecessary() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
adapter?.addScrollableFooter(SpacerItem(200))
}
}
@Suppress("LongMethod") @Suppress("LongMethod")
private fun initObservers() { private fun initObservers() {
this.lifecycleScope.launch { this.lifecycleScope.launch {
@ -963,8 +971,7 @@ class ConversationsListActivity :
} else { } else {
showToolbar() showToolbar()
} }
colorizeStatusBar() initSystemBars()
colorizeNavigationBar()
} }
} }

View File

@ -21,6 +21,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
@ -28,8 +29,9 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.lifecycle.ViewModelProvider import androidx.compose.ui.unit.dp
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.lifecycle.ViewModelProvider
import autodagger.AutoInjector import autodagger.AutoInjector
import com.nextcloud.talk.BuildConfig import com.nextcloud.talk.BuildConfig
import com.nextcloud.talk.R import com.nextcloud.talk.R
@ -37,8 +39,8 @@ import com.nextcloud.talk.activities.BaseActivity
import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager
import com.nextcloud.talk.components.ColoredStatusBar
import com.nextcloud.talk.components.StandardAppBar import com.nextcloud.talk.components.StandardAppBar
import com.nextcloud.talk.components.SetupSystemBars
import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.users.UserManager
import com.nextcloud.talk.utils.BrandingUtils import com.nextcloud.talk.utils.BrandingUtils
import com.nextcloud.talk.utils.ClosedInterfaceImpl import com.nextcloud.talk.utils.ClosedInterfaceImpl
@ -109,18 +111,22 @@ class DiagnoseActivity : BaseActivity() {
MaterialTheme( MaterialTheme(
colorScheme = colorScheme colorScheme = colorScheme
) { ) {
ColoredStatusBar()
Scaffold( Scaffold(
modifier = Modifier
.statusBarsPadding(),
topBar = { topBar = {
StandardAppBar( StandardAppBar(
title = stringResource(R.string.nc_settings_diagnose_title), title = stringResource(R.string.nc_settings_diagnose_title),
menuItems menuItems
) )
}, },
content = { content = { paddingValues ->
val viewState = diagnoseViewModel.notificationViewState.collectAsState().value val viewState = diagnoseViewModel.notificationViewState.collectAsState().value
Column( Column(
Modifier Modifier
.padding(it) .padding(0.dp, paddingValues.calculateTopPadding(), 0.dp, 0.dp)
.background(backgroundColor) .background(backgroundColor)
.fillMaxSize() .fillMaxSize()
) { ) {
@ -136,7 +142,6 @@ class DiagnoseActivity : BaseActivity() {
} }
} }
) )
SetupSystemBars()
} }
} }
} }

View File

@ -65,7 +65,12 @@ fun DiagnoseContentComposable(
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.padding(16.dp) .padding(
start = 16.dp,
top = 0.dp,
end = 16.dp,
bottom = 0.dp
)
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
) { ) {
data.value.forEach { element -> data.value.forEach { element ->
@ -100,6 +105,7 @@ fun DiagnoseContentComposable(
ShowTestPushButton(onTestPushClick) ShowTestPushButton(onTestPushClick)
} }
ShowNotificationData(isLoading, showDialog, context, viewState, onDismissDialog) ShowNotificationData(isLoading, showDialog, context, viewState, onDismissDialog)
Spacer(modifier = Modifier.height(40.dp))
} }
} }

View File

@ -65,7 +65,7 @@ class InvitationsActivity : BaseActivity() {
binding = ActivityInvitationsBinding.inflate(layoutInflater) binding = ActivityInvitationsBinding.inflate(layoutInflater)
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors() initSystemBars()
adapter = InvitationsAdapter(currentUser) { invitation, action -> adapter = InvitationsAdapter(currentUser) { invitation, action ->
handleInvitation(invitation, action) handleInvitation(invitation, action)

View File

@ -67,7 +67,7 @@ class GeocodingActivity :
binding = ActivityGeocodingBinding.inflate(layoutInflater) binding = ActivityGeocodingBinding.inflate(layoutInflater)
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors() initSystemBars()
Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context)) Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context))

View File

@ -129,7 +129,7 @@ class LocationPickerActivity :
binding = ActivityLocationBinding.inflate(layoutInflater) binding = ActivityLocationBinding.inflate(layoutInflater)
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors() initSystemBars()
getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context)) getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context))

View File

@ -70,7 +70,7 @@ class MessageSearchActivity : BaseActivity() {
binding = ActivityMessageSearchBinding.inflate(layoutInflater) binding = ActivityMessageSearchBinding.inflate(layoutInflater)
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors() initSystemBars()
viewModel = ViewModelProvider(this, viewModelFactory)[MessageSearchViewModel::class.java] viewModel = ViewModelProvider(this, viewModelFactory)[MessageSearchViewModel::class.java]
user = currentUserProvider.currentUser.blockingGet() user = currentUserProvider.currentUser.blockingGet()

View File

@ -57,7 +57,7 @@ class ListOpenConversationsActivity : BaseActivity() {
binding = ActivityOpenConversationsBinding.inflate(layoutInflater) binding = ActivityOpenConversationsBinding.inflate(layoutInflater)
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors() initSystemBars()
viewThemeUtils.platform.colorImageView(binding.searchOpenConversations, ColorRole.ON_SURFACE) viewThemeUtils.platform.colorImageView(binding.searchOpenConversations, ColorRole.ON_SURFACE)
viewThemeUtils.material.colorTextInputLayout(binding.textInputLayout) viewThemeUtils.material.colorTextInputLayout(binding.textInputLayout)

View File

@ -119,7 +119,7 @@ class ProfileActivity : BaseActivity() {
binding = ActivityProfileBinding.inflate(layoutInflater) binding = ActivityProfileBinding.inflate(layoutInflater)
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors() initSystemBars()
} }
override fun onResume() { override fun onResume() {

View File

@ -145,7 +145,7 @@ class SettingsActivity :
binding = ActivitySettingsBinding.inflate(layoutInflater) binding = ActivitySettingsBinding.inflate(layoutInflater)
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors() initSystemBars()
binding.avatarImage.let { ViewCompat.setTransitionName(it, "userAvatar.transitionTag") } binding.avatarImage.let { ViewCompat.setTransitionName(it, "userAvatar.transitionTag") }

View File

@ -13,7 +13,6 @@ import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import androidx.core.content.res.ResourcesCompat
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -28,7 +27,6 @@ import com.nextcloud.talk.databinding.ActivitySharedItemsBinding
import com.nextcloud.talk.shareditems.adapters.SharedItemsAdapter import com.nextcloud.talk.shareditems.adapters.SharedItemsAdapter
import com.nextcloud.talk.shareditems.model.SharedItemType import com.nextcloud.talk.shareditems.model.SharedItemType
import com.nextcloud.talk.shareditems.viewmodels.SharedItemsViewModel import com.nextcloud.talk.shareditems.viewmodels.SharedItemsViewModel
import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CONVERSATION_NAME import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_CONVERSATION_NAME
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
import javax.inject.Inject import javax.inject.Inject
@ -57,15 +55,11 @@ class SharedItemsActivity : BaseActivity() {
setSupportActionBar(binding.sharedItemsToolbar) setSupportActionBar(binding.sharedItemsToolbar)
setContentView(binding.root) setContentView(binding.root)
viewThemeUtils.platform.themeStatusBar(this) initSystemBars()
viewThemeUtils.material.themeToolbar(binding.sharedItemsToolbar) viewThemeUtils.material.themeToolbar(binding.sharedItemsToolbar)
viewThemeUtils.material.themeTabLayoutOnSurface(binding.sharedItemsTabs) viewThemeUtils.material.themeTabLayoutOnSurface(binding.sharedItemsTabs)
DisplayUtils.applyColorToNavigationBar(
this.window,
ResourcesCompat.getColor(resources, R.color.bg_default, null)
)
supportActionBar?.title = conversationName supportActionBar?.title = conversationName
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)

View File

@ -86,7 +86,7 @@ class TranslateActivity : BaseActivity() {
} }
setupActionBar() setupActionBar()
setContentView(binding.root) setContentView(binding.root)
setupSystemColors() initSystemBars()
setupTextViews() setupTextViews()
viewModel.getLanguages() viewModel.getLanguages()
setupCopyButton() setupCopyButton()

View File

@ -0,0 +1,38 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.nextcloud.talk.utils
import android.graphics.Color
import android.os.Build
import androidx.activity.SystemBarStyle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
/**
* This method is similar to "adjustUIForAPILevel35" in
* AppCompatActivityExtensions.kt in https://github.com/nextcloud/android-common/
* Only window.addSystemBarPaddings() had to be removed. This could be unified again at some point.
*/
@JvmOverloads
fun AppCompatActivity.adjustUIForAPILevel35(
statusBarStyle: SystemBarStyle = SystemBarStyle.auto(Color.TRANSPARENT, Color.TRANSPARENT),
// It may make sense to change navigationBarStyle to "SystemBarStyle.auto(Color.TRANSPARENT, Color.TRANSPARENT)"
// For now, it is set to "light" to have a fully transparent navigation bar to align with the XML screens.
// It may be wanted to have a semi transparent navigation bar in the future. Then set it to "auto" and try to
// migrate the XML screens to Compose (having semi transparent navigation bar for XML did not work out. In
// general, supporting both XML and Compose system bar handling is a pain and we will have it easier without XML)
// So in short: migrate all screens to Compose. Then it's easier to decide if navigation bar should be semi
// transparent or not for all screens.
navigationBarStyle: SystemBarStyle = SystemBarStyle.light(Color.TRANSPARENT, Color.TRANSPARENT)
) {
val isApiLevel35OrHigher = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM)
if (!isApiLevel35OrHigher) {
return
}
enableEdgeToEdge(statusBarStyle, navigationBarStyle)
}

View File

@ -91,6 +91,7 @@
</LinearLayout> </LinearLayout>
</com.google.android.material.appbar.MaterialToolbar> </com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<RelativeLayout <RelativeLayout

View File

@ -553,7 +553,7 @@
android:layout_marginTop="@dimen/standard_quarter_margin" android:layout_marginTop="@dimen/standard_quarter_margin"
android:background="?android:attr/selectableItemBackground" android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="@dimen/standard_padding"> android:padding="@dimen/standard_half_padding">
<ImageView <ImageView
android:layout_width="24dp" android:layout_width="24dp"
@ -579,7 +579,7 @@
android:layout_marginTop="@dimen/standard_quarter_margin" android:layout_marginTop="@dimen/standard_quarter_margin"
android:background="?android:attr/selectableItemBackground" android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="@dimen/standard_padding"> android:padding="@dimen/standard_half_padding">
<ImageView <ImageView
android:layout_width="24dp" android:layout_width="24dp"
@ -605,7 +605,7 @@
android:layout_marginTop="@dimen/standard_quarter_margin" android:layout_marginTop="@dimen/standard_quarter_margin"
android:background="?android:attr/selectableItemBackground" android:background="?android:attr/selectableItemBackground"
android:orientation="horizontal" android:orientation="horizontal"
android:padding="@dimen/standard_padding"> android:padding="@dimen/standard_half_padding">
<ImageView <ImageView
android:layout_width="24dp" android:layout_width="24dp"
@ -625,6 +625,9 @@
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<Space
android:layout_width="match_parent"
android:layout_height="50dp" />
</LinearLayout> </LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>
</LinearLayout> </LinearLayout>

View File

@ -292,7 +292,8 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="bottom|end" android:layout_gravity="bottom|end"
android:layout_margin="16dp" android:layout_marginEnd="16dp"
android:layout_marginBottom="36dp"
android:contentDescription="@string/nc_new_conversation" android:contentDescription="@string/nc_new_conversation"
app:borderWidth="0dp" app:borderWidth="0dp"
app:srcCompat="@drawable/ic_pencil_grey600_24dp" app:srcCompat="@drawable/ic_pencil_grey600_24dp"

View File

@ -906,6 +906,9 @@
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
<Space
android:layout_width="match_parent"
android:layout_height="50dp" />
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
</LinearLayout> </LinearLayout>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2025 Marcel Hibbe <dev@mhibbe.de>
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="0dp"/>

View File

@ -29,6 +29,9 @@
<item name="popupMenuStyle">@style/ChatSendButtonMenu</item> <item name="popupMenuStyle">@style/ChatSendButtonMenu</item>
<item name="dialogCornerRadius">@dimen/dialogBorderRadius</item> <item name="dialogCornerRadius">@dimen/dialogBorderRadius</item>
<item name="android:windowBackground">@color/bg_default</item> <item name="android:windowBackground">@color/bg_default</item>
<!-- <item name="android:windowTranslucentStatus">false</item>-->
<!-- <item name="android:windowDrawsSystemBarBackgrounds">true</item>-->
<!-- <item name="android:statusBarColor">@android:color/transparent</item>-->
</style> </style>
<style name="ThemeOverlay.AppTheme.PopupMenu" parent="ThemeOverlay.Material3.Dark"> <style name="ThemeOverlay.AppTheme.PopupMenu" parent="ThemeOverlay.Material3.Dark">

View File

@ -1383,6 +1383,8 @@ vCeonVI7Q1CkIHt8u7eMgzfEkaiPLZlI0l0RpfT4pnNieqg=
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub BAC30622339994C4 pub BAC30622339994C4
uid Chris Povirk <cpovirk@google.com>
sub FC9BDC25FB378008 sub FC9BDC25FB378008
-----BEGIN PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----
@ -1391,20 +1393,21 @@ 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
i8/b+PwSW+nW3EpQZdLqZtOU QzLSAVn44AHSomlgzecMR6RZk/fwbzSSiOc3rW1mNFOG70iLz9v4/BJb6dbcSlBl
=2H2i 0upm05Q=
=Gf3Y
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub BCF4173966770193 pub BCF4173966770193
@ -1433,15 +1436,18 @@ IaddzrPZPmaZ8CtzzyB7+JdSNItBB2Sp
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub BDD2A76422470515 pub BDD2A76422470515
uid Dave Brosius <dbrosius@mebigfatguy.com>
sub 0C77E993AC36C97C sub 0C77E993AC36C97C
-----BEGIN PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEaDypvxYJKwYBBAHaRw8BAQdAv3OEFRIQWBhSii0M3S9P3eGlZLalGY9smzBQ mDMEaDypvxYJKwYBBAHaRw8BAQdAv3OEFRIQWBhSii0M3S9P3eGlZLalGY9smzBQ
C0aiVXW4OARoPKm/EgorBgEEAZdVAQUBAQdA2THBTS3MqZPdTuKmc7QkAvlvwmJa C0aiVXW0J0RhdmUgQnJvc2l1cyA8ZGJyb3NpdXNAbWViaWdmYXRndXkuY29tPrg4
WEQsXXqkjQdEwD4DAQgHiH4EGBYKACYWIQSu/rh4kM398rwIxKq90qdkIkcFFQUC BGg8qb8SCisGAQQBl1UBBQEBB0DZMcFNLcypk91O4qZztCQC+W/CYlpYRCxdeqSN
aDypvwIbDAUJBaOagAAKCRC90qdkIkcFFfyUAPsGJcpKQP2/sQe+XN69rVZMFXhk B0TAPgMBCAeIfgQYFgoAJhYhBK7+uHiQzf3yvAjEqr3Sp2QiRwUVBQJoPKm/AhsM
dYg0U9EhpY/7GHDpHQD+J5Uy2s3USLxeyIylXUFWtxqOocB+vZhvH3Yhmjhwmgw= BQkFo5qAAAoJEL3Sp2QiRwUV/JQA+wYlykpA/b+xB75c3r2tVkwVeGR1iDRT0SGl
=zAHg j/sYcOkdAP4nlTLazdRIvF7IjKVdQVa3Go6hwH69mG8fdiGaOHCaDA==
=wcNA
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub BEDE11EAF1164480 pub BEDE11EAF1164480
@ -6180,8 +6186,6 @@ c8LNGrDaCFdXnOdlNV/zT9VvBk/RkV+Tl/Lk4g==
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub 7905DE25C78AD456 pub 7905DE25C78AD456
uid Protobuf Release <protobuf@googlegroups.com>
sub DBC5123E2E98FEFE sub DBC5123E2E98FEFE
-----BEGIN PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----
@ -6193,26 +6197,25 @@ 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 =UiVm
=z4dc
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub 793FD5751A0F0780 pub 793FD5751A0F0780

View File

@ -34,8 +34,10 @@
<trusted-key id="0F06FF86BEEAF4E71866EE5232EE5355A6BC6E42"> <trusted-key id="0F06FF86BEEAF4E71866EE5232EE5355A6BC6E42">
<trusting group="androidx.appcompat"/> <trusting group="androidx.appcompat"/>
<trusting group="androidx.camera"/> <trusting group="androidx.camera"/>
<trusting group="androidx.collection"/>
<trusting group="androidx.compose.runtime"/> <trusting group="androidx.compose.runtime"/>
<trusting group="androidx.constraintlayout"/> <trusting group="androidx.constraintlayout"/>
<trusting group="androidx.core"/>
<trusting group="androidx.databinding"/> <trusting group="androidx.databinding"/>
<trusting group="androidx.datastore"/> <trusting group="androidx.datastore"/>
<trusting group="androidx.exifinterface" name="exifinterface" version="1.4.0"/> <trusting group="androidx.exifinterface" name="exifinterface" version="1.4.0"/>
@ -235,7 +237,10 @@
<trusting group="^androidx[.]test($|([.].*))" regex="true"/> <trusting group="^androidx[.]test($|([.].*))" regex="true"/>
<trusting group="^com[.]android($|([.].*))" regex="true"/> <trusting group="^com[.]android($|([.].*))" regex="true"/>
</trusted-key> </trusted-key>
<trusted-key id="A6D6C97108B8585F91B158748671A8DF71296252" group="com.squareup" name="javapoet" version="1.10.0"/> <trusted-key id="A6D6C97108B8585F91B158748671A8DF71296252">
<trusting name="javapoet" group="com.squareup" version="1.10.0"/>
<trusting group="com.squareup.okhttp3"/>
</trusted-key>
<trusted-key id="A7892505CF1A58076453E52D7999BEFBA1039E8B" group="net.bytebuddy"/> <trusted-key id="A7892505CF1A58076453E52D7999BEFBA1039E8B" group="net.bytebuddy"/>
<trusted-key id="AA417737BD805456DB3CBDDE6601E5C08DCCBB96" group="info.picocli" name="picocli" version="4.7.5"/> <trusted-key id="AA417737BD805456DB3CBDDE6601E5C08DCCBB96" group="info.picocli" name="picocli" version="4.7.5"/>
<trusted-key id="AA70C7C433D501636392EC02153E7A3C2B4E5118" group="org.eclipse.ee4j" name="project"/> <trusted-key id="AA70C7C433D501636392EC02153E7A3C2B4E5118" group="org.eclipse.ee4j" name="project"/>
@ -252,7 +257,10 @@
<trusting group="joda-time" name="joda-time" version="2.13.1"/> <trusting group="joda-time" name="joda-time" version="2.13.1"/>
<trusting group="joda-time" name="joda-time" version="2.14.0"/> <trusting group="joda-time" name="joda-time" version="2.14.0"/>
</trusted-key> </trusted-key>
<trusted-key id="B6E73D84EA4FCC47166087253FAAD2CD5ECBB314" group="org.apache.commons" name="commons-parent" version="52"/> <trusted-key id="B6E73D84EA4FCC47166087253FAAD2CD5ECBB314">
<trusting group="org.apache.commons"/>
<trusting name="commons-parent" group="org.apache.commons" version="52"/>
</trusted-key>
<trusted-key id="B801E2F8EF035068EC1139CC29579F18FA8FD93B" group="com.google.j2objc" name="j2objc-annotations" version="1.3"/> <trusted-key id="B801E2F8EF035068EC1139CC29579F18FA8FD93B" group="com.google.j2objc" name="j2objc-annotations" version="1.3"/>
<trusted-key id="BC87A3FD0A54480F0BADBEBD21939FF0CA2A6567" group="commons-codec" name="commons-codec" version="1.15"/> <trusted-key id="BC87A3FD0A54480F0BADBEBD21939FF0CA2A6567" group="commons-codec" name="commons-codec" version="1.15"/>
<trusted-key id="BCC135FC7ED8214F823D73E97FE9900F412D622E" group="com.google.flatbuffers" name="flatbuffers-java" version="1.12.0"/> <trusted-key id="BCC135FC7ED8214F823D73E97FE9900F412D622E" group="com.google.flatbuffers" name="flatbuffers-java" version="1.12.0"/>
@ -332,6 +340,11 @@
<sha256 value="27a4be7462629c312da0b831a0978d2076fc34074145fb61dd4e86d7c8469b82" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="27a4be7462629c312da0b831a0978d2076fc34074145fb61dd4e86d7c8469b82" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact> </artifact>
</component> </component>
<component name="activity" group="androidx.activity" version="1.1.0">
<artifact name="activity-1.1.0.pom">
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="3690001fc5a57ad176cacf7a13f56219bffb73b93c7978dbac1e1e5db082d6c0"/>
</artifact>
</component>
<component group="androidx.activity" name="activity" version="1.2.4"> <component group="androidx.activity" name="activity" version="1.2.4">
<artifact name="activity-1.2.4.aar"> <artifact name="activity-1.2.4.aar">
<sha256 value="ae8e9c7de57e387d2ad90e73f3a5a5dfd502bd4f034c1dccfdb3506d1d2df81a" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="ae8e9c7de57e387d2ad90e73f3a5a5dfd502bd4f034c1dccfdb3506d1d2df81a" origin="Generated by Gradle" reason="Artifact is not signed"/>
@ -974,6 +987,11 @@
<sha256 value="cf968e0494335d200dc0a2bf82df7501b14bbccde74d615672ef8b915cd6045a" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="cf968e0494335d200dc0a2bf82df7501b14bbccde74d615672ef8b915cd6045a" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact> </artifact>
</component> </component>
<component name="compose-bom" group="androidx.compose" version="2025.06.00">
<artifact name="compose-bom-2025.06.00.pom">
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="a8b9c186caa05ec7bf27fc33db0c1b494a78b4f9a0c3ce1fa3c6f6b970ddc5ec"/>
</artifact>
</component>
<component group="androidx.compose.animation" name="animation" version="1.7.7"> <component group="androidx.compose.animation" name="animation" version="1.7.7">
<artifact name="animation-1.7.7.module"> <artifact name="animation-1.7.7.module">
<sha256 value="3431b3d00a8e6e0d54aff825a0a66402d8e924c2b2e6a165669e4f41c7a63fc9" origin="Generated by Gradle"/> <sha256 value="3431b3d00a8e6e0d54aff825a0a66402d8e924c2b2e6a165669e4f41c7a63fc9" origin="Generated by Gradle"/>
@ -1970,6 +1988,11 @@
<sha256 value="69b79724566d49140846700690b8d2165231c577e93e66726a443e8f976bbe19" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="69b79724566d49140846700690b8d2165231c577e93e66726a443e8f976bbe19" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact> </artifact>
</component> </component>
<component name="constraintlayout" group="androidx.constraintlayout" version="1.1.3">
<artifact name="constraintlayout-1.1.3.pom">
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="a47057d0a9b23342c3779d3d56b60944997e98f0c5d8886fda29e4f1074d9ea6"/>
</artifact>
</component>
<component group="androidx.constraintlayout" name="constraintlayout" version="2.0.1"> <component group="androidx.constraintlayout" name="constraintlayout" version="2.0.1">
<artifact name="constraintlayout-2.0.1.aar"> <artifact name="constraintlayout-2.0.1.aar">
<sha256 value="ec15b5d4a2eff07888bc1499ce2e2c6efe24c0ed60cc57b08c9dc4b6fd3c2189" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="ec15b5d4a2eff07888bc1499ce2e2c6efe24c0ed60cc57b08c9dc4b6fd3c2189" origin="Generated by Gradle" reason="Artifact is not signed"/>
@ -2079,6 +2102,11 @@
<sha256 value="2a10979bbb3bcd7b25b7f664ab4e9b016fabf2174a26768b677e12e4bea4c7c4" origin="Generated by Gradle"/> <sha256 value="2a10979bbb3bcd7b25b7f664ab4e9b016fabf2174a26768b677e12e4bea4c7c4" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component name="core" group="androidx.core" version="1.16.0">
<artifact name="core-1.16.0.aar">
<sha256 origin="Generated by Gradle" value="6bf03d39dbe3744acce227d3b697374c3625aae1025fbec8ad9fd7bd58bce431"/>
</artifact>
</component>
<component group="androidx.core" name="core" version="1.2.0"> <component group="androidx.core" name="core" version="1.2.0">
<artifact name="core-1.2.0.aar"> <artifact name="core-1.2.0.aar">
<sha256 value="524b8b88ceb6a74a7e44e6b567a135660f211799904cb218bfee5be1166820b2" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="524b8b88ceb6a74a7e44e6b567a135660f211799904cb218bfee5be1166820b2" origin="Generated by Gradle" reason="Artifact is not signed"/>
@ -2113,6 +2141,11 @@
<sha256 value="8674ade1d12962469dd2d1e6edc03b465f20d180b0840a129bc40b351e8651d1" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="8674ade1d12962469dd2d1e6edc03b465f20d180b0840a129bc40b351e8651d1" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact> </artifact>
</component> </component>
<component name="core-ktx" group="androidx.core" version="1.1.0">
<artifact name="core-ktx-1.1.0.pom">
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="729d11bad16d87c6212dc9ab80e9c770d333115062136e0732164a6b1696e11c"/>
</artifact>
</component>
<component group="androidx.core" name="core-ktx" version="1.13.1"> <component group="androidx.core" name="core-ktx" version="1.13.1">
<artifact name="core-ktx-1.13.1.aar"> <artifact name="core-ktx-1.13.1.aar">
<sha256 value="19ba50d094c7368ede1b4ccf1195ceb83e35970736593f823e5af716f8d05d70" origin="Generated by Gradle"/> <sha256 value="19ba50d094c7368ede1b4ccf1195ceb83e35970736593f823e5af716f8d05d70" origin="Generated by Gradle"/>
@ -3011,7 +3044,7 @@
<sha256 value="8770c180103e0b8c04a07eb4c59153af639b09eca25deae9bdcdaf869d1e5b6b" origin="Generated by Gradle"/> <sha256 value="8770c180103e0b8c04a07eb4c59153af639b09eca25deae9bdcdaf869d1e5b6b" origin="Generated by Gradle"/>
</artifact> </artifact>
<artifact name="exifinterface-1.3.2.module"> <artifact name="exifinterface-1.3.2.module">
<sha256 value="10ba5b5cbea7f5c8758be4fdaec60a3545e891a1130d830a442b88cf5336a885" origin="Generated by Gradle"/> <sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="10ba5b5cbea7f5c8758be4fdaec60a3545e891a1130d830a442b88cf5336a885"/>
</artifact> </artifact>
</component> </component>
<component group="androidx.exifinterface" name="exifinterface" version="1.3.6"> <component group="androidx.exifinterface" name="exifinterface" version="1.3.6">
@ -10235,6 +10268,14 @@
<sha256 value="16df4da63602c412d8712018c4b35ce24cb040761bcbc026fbcd836dbe953171" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="16df4da63602c412d8712018c4b35ce24cb040761bcbc026fbcd836dbe953171" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact> </artifact>
</component> </component>
<component name="core" group="com.github.nextcloud.android-common" version="0.26.0">
<artifact name="core-0.26.0.aar">
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="933d612d1324b21d2e7e04a890bb2c7afda4ffdbe91b76fdea625976f14ba1fb"/>
</artifact>
<artifact name="core-0.26.0.module">
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="b0194f2d5ce11e87603eb9d8d0f61a38442cf310d6445e02bb7c04b593d04ebd"/>
</artifact>
</component>
<component group="com.github.nextcloud.android-common" name="material-color-utilities" version="0.18.0"> <component group="com.github.nextcloud.android-common" name="material-color-utilities" version="0.18.0">
<artifact name="material-color-utilities-0.18.0.jar"> <artifact name="material-color-utilities-0.18.0.jar">
<sha256 value="e04a3f4a3caff6e4b2ce3f14f91f0485ab1f012af652102eba61ab6bcf3d8240" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="e04a3f4a3caff6e4b2ce3f14f91f0485ab1f012af652102eba61ab6bcf3d8240" origin="Generated by Gradle" reason="Artifact is not signed"/>
@ -10299,6 +10340,14 @@
<sha256 value="ca3c0835e5534a549d3718380982ba8cead70613ca436d65606f16cd2e3a0f01" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="ca3c0835e5534a549d3718380982ba8cead70613ca436d65606f16cd2e3a0f01" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact> </artifact>
</component> </component>
<component name="material-color-utilities" group="com.github.nextcloud.android-common" version="0.26.0">
<artifact name="material-color-utilities-0.26.0.jar">
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="64c9e61afb6fd0d4ee03dd394429ab1c393f5b66429e036b618285d1bb7d8160"/>
</artifact>
<artifact name="material-color-utilities-0.26.0.module">
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="6e646b238fad314fcbb72e59b198e2d39183191a7fd2dff273ef3e924cf1b915"/>
</artifact>
</component>
<component group="com.github.nextcloud.android-common" name="ui" version="0.18.0"> <component group="com.github.nextcloud.android-common" name="ui" version="0.18.0">
<artifact name="ui-0.18.0.aar"> <artifact name="ui-0.18.0.aar">
<sha256 value="7d900a930d7ad1f7de91177b8b661abef13deef032493cee99fe9842f85bcf16" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="7d900a930d7ad1f7de91177b8b661abef13deef032493cee99fe9842f85bcf16" origin="Generated by Gradle" reason="Artifact is not signed"/>
@ -10363,6 +10412,14 @@
<sha256 value="4af371de8c6cd41a24f1a3ade9cd010c5d226a583d95ff909b1ca80f02d86db6" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="4af371de8c6cd41a24f1a3ade9cd010c5d226a583d95ff909b1ca80f02d86db6" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact> </artifact>
</component> </component>
<component name="ui" group="com.github.nextcloud.android-common" version="0.26.0">
<artifact name="ui-0.26.0.aar">
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="6a34b9c6e11d1ad2e6578421f9432997b62ca456e41ffcc0c2cbfaa508eb9f11"/>
</artifact>
<artifact name="ui-0.26.0.module">
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="7aadbf0d9e84d63996bdc9f70fdb36a15e633fccda902627241d418bf8363e25"/>
</artifact>
</component>
<component group="com.github.spotbugs" name="spotbugs" version="4.8.6"> <component group="com.github.spotbugs" name="spotbugs" version="4.8.6">
<artifact name="spotbugs-4.8.6.jar"> <artifact name="spotbugs-4.8.6.jar">
<sha256 value="69fde8787971a26b2372d416015d806bf7df4f847f7121bd5eeef239324cf180" origin="Generated by Gradle"/> <sha256 value="69fde8787971a26b2372d416015d806bf7df4f847f7121bd5eeef239324cf180" origin="Generated by Gradle"/>
@ -10560,6 +10617,11 @@
<sha256 value="96f6e6d9f5e5db840ee3da20449e16828ed4ba2c07783dde3397d13aaf814e19" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="96f6e6d9f5e5db840ee3da20449e16828ed4ba2c07783dde3397d13aaf814e19" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact> </artifact>
</component> </component>
<component name="play-services-base" group="com.google.android.gms" version="18.1.0">
<artifact name="play-services-base-18.1.0.pom">
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="30df78ba3ead133c2b36784b425a9eeee7f02531907e8aaee4e8922354f732a7"/>
</artifact>
</component>
<component group="com.google.android.gms" name="play-services-base" version="18.2.0"> <component group="com.google.android.gms" name="play-services-base" version="18.2.0">
<artifact name="play-services-base-18.2.0.aar"> <artifact name="play-services-base-18.2.0.aar">
<sha256 value="ba1efe418b7e2696878cc604c27dc7af32a2c71462df55632307c909aa9c2e11" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="ba1efe418b7e2696878cc604c27dc7af32a2c71462df55632307c909aa9c2e11" origin="Generated by Gradle" reason="Artifact is not signed"/>
@ -10704,6 +10766,11 @@
<sha256 value="9ddba12b5c80444c45413f043b34fd3127c2493c506a9db1ecbfe63039d83e34" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="9ddba12b5c80444c45413f043b34fd3127c2493c506a9db1ecbfe63039d83e34" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact> </artifact>
</component> </component>
<component name="material" group="com.google.android.material" version="1.3.0">
<artifact name="material-1.3.0.module">
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="5d6b782ba57e549b8f00bc902664085e9a63c11e177f934589ba6331a764543b"/>
</artifact>
</component>
<component group="com.google.android.material" name="material" version="1.4.0"> <component group="com.google.android.material" name="material" version="1.4.0">
<artifact name="material-1.4.0.aar"> <artifact name="material-1.4.0.aar">
<sha256 value="80a0e02abf8a8a8cbe5716e06ac80cd683840b9f5b0d2f19a2a279e47f2895ee" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="80a0e02abf8a8a8cbe5716e06ac80cd683840b9f5b0d2f19a2a279e47f2895ee" origin="Generated by Gradle" reason="Artifact is not signed"/>
@ -10712,6 +10779,11 @@
<sha256 value="91eecf4b1272aacc4fdb41fefaa6324cbd36218c51866d300dcf237670e4e0cc" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="91eecf4b1272aacc4fdb41fefaa6324cbd36218c51866d300dcf237670e4e0cc" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact> </artifact>
</component> </component>
<component name="material" group="com.google.android.material" version="1.8.0">
<artifact name="material-1.8.0.module">
<sha256 origin="Generated by Gradle" reason="Artifact is not signed" value="94935b8018ddb4ef844eb107c46f2fa2bc6b548cf6642c26e30ab3ac6daa77ab"/>
</artifact>
</component>
<component group="com.google.api.grpc" name="proto-google-common-protos" version="2.0.1"> <component group="com.google.api.grpc" name="proto-google-common-protos" version="2.0.1">
<artifact name="proto-google-common-protos-2.0.1.pom"> <artifact name="proto-google-common-protos-2.0.1.pom">
<sha256 value="8b62bfd85d693ebcffd828232af7424f34fd212c5e28e5ed99b0dc5d2bc7d4f5" origin="Generated by Gradle"/> <sha256 value="8b62bfd85d693ebcffd828232af7424f34fd212c5e28e5ed99b0dc5d2bc7d4f5" origin="Generated by Gradle"/>
@ -11141,6 +11213,11 @@
<sha256 value="14ecb4776a8071e86129833319431399b2a69e6e9bfedcb2992538bdaca6cfc0" origin="Generated by Gradle"/> <sha256 value="14ecb4776a8071e86129833319431399b2a69e6e9bfedcb2992538bdaca6cfc0" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component name="symbol-processing-api" group="com.google.devtools.ksp" version="2.1.21-2.0.2">
<artifact name="symbol-processing-api-2.1.21-2.0.2.module">
<sha256 origin="Generated by Gradle" value="763cb8bfabf57ae1ac3c5c69baed6cf6a849eaa90b1222d87e8ddf754222168e"/>
</artifact>
</component>
<component group="com.google.devtools.ksp" name="symbol-processing-cmdline" version="2.1.10-1.0.29"> <component group="com.google.devtools.ksp" name="symbol-processing-cmdline" version="2.1.10-1.0.29">
<artifact name="symbol-processing-cmdline-2.1.10-1.0.29.jar"> <artifact name="symbol-processing-cmdline-2.1.10-1.0.29.jar">
<sha256 value="b5c69be50ef939a21c23d1132457ce1566a0aced2c44cabceca8788320df58b8" origin="Generated by Gradle"/> <sha256 value="b5c69be50ef939a21c23d1132457ce1566a0aced2c44cabceca8788320df58b8" origin="Generated by Gradle"/>
@ -14300,6 +14377,11 @@
<sha256 value="80eb61b0c87fdd826a069313b28b672da3f1885832da447b51e6e8a6197e7ecb" origin="Generated by Gradle"/> <sha256 value="80eb61b0c87fdd826a069313b28b672da3f1885832da447b51e6e8a6197e7ecb" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component name="commons-parent" group="org.apache.commons" version="78">
<artifact name="commons-parent-78.pom">
<sha256 origin="Generated by Gradle" value="022d202e655edd04f2a10ecbe453d92977924d38380a4ca8c359f1817a80320e"/>
</artifact>
</component>
<component group="org.apache.commons" name="commons-text" version="1.10.0"> <component group="org.apache.commons" name="commons-text" version="1.10.0">
<artifact name="commons-text-1.10.0.jar"> <artifact name="commons-text-1.10.0.jar">
<sha256 value="770cd903fa7b604d1f7ef7ba17f84108667294b2b478be8ed1af3bffb4ae0018" origin="Generated by Gradle"/> <sha256 value="770cd903fa7b604d1f7ef7ba17f84108667294b2b478be8ed1af3bffb4ae0018" origin="Generated by Gradle"/>
@ -17219,6 +17301,11 @@
<sha256 value="e67459d4882424ac6374f40db1c8f4a2e88946b340ba072c80be932a2be4644d" origin="Generated by Gradle"/> <sha256 value="e67459d4882424ac6374f40db1c8f4a2e88946b340ba072c80be932a2be4644d" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component name="junit-bom" group="org.junit" version="5.11.2">
<artifact name="junit-bom-5.11.2.pom">
<sha256 origin="Generated by Gradle" value="f48e88538aac145eb3ae0345a9ebd055b28f329a35dce8d1e9281325ca9b0ea2"/>
</artifact>
</component>
<component group="org.junit" name="junit-bom" version="5.11.4"> <component group="org.junit" name="junit-bom" version="5.11.4">
<artifact name="junit-bom-5.11.4.module"> <artifact name="junit-bom-5.11.4.module">
<sha256 value="a9a4f27be94e99b9d570162d246a80f686d277d5d31aeb5481047cf51daf46e4" origin="Generated by Gradle"/> <sha256 value="a9a4f27be94e99b9d570162d246a80f686d277d5d31aeb5481047cf51daf46e4" origin="Generated by Gradle"/>