diff --git a/app/build.gradle b/app/build.gradle index 40ee86208..82bc62ef0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,13 +28,13 @@ apply plugin: "org.jlleitschuh.gradle.ktlint" apply plugin: 'kotlinx-serialization' android { - compileSdk 34 + compileSdk 35 namespace 'com.nextcloud.talk' defaultConfig { minSdkVersion 26 - targetSdkVersion 34 + targetSdkVersion 35 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // 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.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' gplayImplementation 'com.google.android.gms:play-services-base:18.6.0' diff --git a/app/src/main/java/com/nextcloud/talk/account/AccountVerificationActivity.kt b/app/src/main/java/com/nextcloud/talk/account/AccountVerificationActivity.kt index 1eb50c189..e23b90b41 100644 --- a/app/src/main/java/com/nextcloud/talk/account/AccountVerificationActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/account/AccountVerificationActivity.kt @@ -91,7 +91,7 @@ class AccountVerificationActivity : BaseActivity() { requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT setContentView(binding.root) actionBar?.hide() - setupSystemColors() + initSystemBars() handleIntent() } diff --git a/app/src/main/java/com/nextcloud/talk/account/ServerSelectionActivity.kt b/app/src/main/java/com/nextcloud/talk/account/ServerSelectionActivity.kt index 473263568..6f111b6d5 100644 --- a/app/src/main/java/com/nextcloud/talk/account/ServerSelectionActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/account/ServerSelectionActivity.kt @@ -78,7 +78,7 @@ class ServerSelectionActivity : BaseActivity() { requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT setContentView(binding.root) actionBar?.hide() - setupSystemColors() + initSystemBars() onBackPressedDispatcher.addCallback(this, onBackPressedCallback) } diff --git a/app/src/main/java/com/nextcloud/talk/account/SwitchAccountActivity.kt b/app/src/main/java/com/nextcloud/talk/account/SwitchAccountActivity.kt index 6b137c2d0..81dcd9939 100644 --- a/app/src/main/java/com/nextcloud/talk/account/SwitchAccountActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/account/SwitchAccountActivity.kt @@ -86,7 +86,7 @@ class SwitchAccountActivity : BaseActivity() { requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT setContentView(binding.root) setupActionBar() - setupSystemColors() + initSystemBars() Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context)) diff --git a/app/src/main/java/com/nextcloud/talk/account/WebViewLoginActivity.kt b/app/src/main/java/com/nextcloud/talk/account/WebViewLoginActivity.kt index 85d124a95..8a71ee57d 100644 --- a/app/src/main/java/com/nextcloud/talk/account/WebViewLoginActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/account/WebViewLoginActivity.kt @@ -114,7 +114,7 @@ class WebViewLoginActivity : BaseActivity() { requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT setContentView(binding.root) actionBar?.hide() - setupSystemColors() + initSystemBars() onBackPressedDispatcher.addCallback(this, onBackPressedCallback) handleIntent() diff --git a/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt index 75bd8c418..c85ad6f82 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt @@ -11,11 +11,13 @@ package com.nextcloud.talk.activities import android.annotation.SuppressLint import android.content.Context import android.content.Intent +import android.os.Build import android.os.Bundle import android.text.TextUtils import android.util.Log import android.view.View import android.view.ViewGroup +import android.view.WindowInsets import android.view.WindowManager import android.view.inputmethod.EditorInfo 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.FileViewerUtils import com.nextcloud.talk.utils.UriUtils +import com.nextcloud.talk.utils.adjustUIForAPILevel35 import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew import com.nextcloud.talk.utils.preferences.AppPreferences @@ -81,6 +84,7 @@ open class BaseActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) + adjustUIForAPILevel35() super.onCreate(savedInstanceState) cleanTempCertPreference() @@ -111,9 +115,22 @@ open class BaseActivity : AppCompatActivity() { eventBus.unregister(this) } - fun setupSystemColors() { - colorizeStatusBar() - colorizeNavigationBar() + /* + * 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() + colorizeNavigationBar() + } + insets + } } open fun colorizeStatusBar() { diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/SpacerItem.kt b/app/src/main/java/com/nextcloud/talk/adapters/items/SpacerItem.kt new file mode 100644 index 000000000..243f8278c --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/SpacerItem.kt @@ -0,0 +1,41 @@ +/* + * Nextcloud Talk - Android Client + * + * SPDX-FileCopyrightText: 2025 Marcel Hibbe + * 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() { + + override fun getLayoutRes(): Int = R.layout.item_spacer + + override fun createViewHolder(view: View?, adapter: FlexibleAdapter?>?): ViewHolder { + return ViewHolder(view!!, adapter!!) + } + + override fun bindViewHolder( + adapter: FlexibleAdapter?>?, + holder: ViewHolder, + position: Int, + payloads: MutableList? + ) { + 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) +} diff --git a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt index 5afe97ce0..8c8bf3832 100644 --- a/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt @@ -66,6 +66,8 @@ import androidx.core.graphics.drawable.toDrawable import androidx.core.net.toUri import androidx.core.os.bundleOf import androidx.core.text.bold +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat import androidx.emoji2.text.EmojiCompat import androidx.fragment.app.DialogFragment import androidx.fragment.app.commit @@ -458,7 +460,28 @@ class ChatActivity : binding = ActivityChatBinding.inflate(layoutInflater) setupActionBar() 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() handleIntent(intent) @@ -486,7 +509,7 @@ class ChatActivity : initObservers() pickMultipleMedia = registerForActivityResult( - ActivityResultContracts.PickMultipleVisualMedia(5) + ActivityResultContracts.PickMultipleVisualMedia(MAX_AMOUNT_MEDIA_FILE_PICKER) ) { uris -> if (uris.isNotEmpty()) { onChooseFileResult(uris) @@ -684,7 +707,7 @@ class ChatActivity : ?.split("#") ?.getOrNull(1) ?.toLongOrNull() - val currentTimeStamp = (System.currentTimeMillis() / 1000).toLong() + val currentTimeStamp = (System.currentTimeMillis() / ONE_SECOND_IN_MILLIS).toLong() val retentionPeriod = retentionOfEventRooms(spreedCapabilities) val isPastEvent = eventEndTimeStamp?.let { it < currentTimeStamp } if (isPastEvent == true && retentionPeriod != 0) { @@ -4193,5 +4216,6 @@ class ChatActivity : const val OUT_OF_OFFICE_ALPHA = 76 const val ZERO_INDEX = 0 const val ONE_INDEX = 1 + const val MAX_AMOUNT_MEDIA_FILE_PICKER = 10 } } diff --git a/app/src/main/java/com/nextcloud/talk/components/SetupSystemBars.kt b/app/src/main/java/com/nextcloud/talk/components/ColoredStatusBar.kt similarity index 54% rename from app/src/main/java/com/nextcloud/talk/components/SetupSystemBars.kt rename to app/src/main/java/com/nextcloud/talk/components/ColoredStatusBar.kt index 5c36286c6..60613a401 100644 --- a/app/src/main/java/com/nextcloud/talk/components/SetupSystemBars.kt +++ b/app/src/main/java/com/nextcloud/talk/components/ColoredStatusBar.kt @@ -1,7 +1,6 @@ /* * Nextcloud Talk - Android Client * - * SPDX-FileCopyrightText: 2024 Sowjanya Kota * SPDX-FileCopyrightText: 2025 Marcel Hibbe * SPDX-License-Identifier: GPL-3.0-or-later */ @@ -9,16 +8,41 @@ package com.nextcloud.talk.components import android.app.Activity +import android.os.Build +import androidx.compose.foundation.background 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.runtime.Composable import androidx.compose.runtime.DisposableEffect +import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat @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 isDarkMode = isSystemInDarkTheme() val statusBarColor = MaterialTheme.colorScheme.surface.toArgb() diff --git a/app/src/main/java/com/nextcloud/talk/components/VerticallyCenteredRow.kt b/app/src/main/java/com/nextcloud/talk/components/VerticallyCenteredRow.kt new file mode 100644 index 000000000..71d5a08de --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/components/VerticallyCenteredRow.kt @@ -0,0 +1,24 @@ +/* + * Nextcloud Talk - Android Client + * + * SPDX-FileCopyrightText: 2025 Marcel Hibbe + * 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 + ) +} diff --git a/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivity.kt b/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivity.kt index b0031a27f..5f93ddf75 100644 --- a/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/contacts/ContactsActivity.kt @@ -18,9 +18,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import autodagger.AutoInjector import com.nextcloud.talk.activities.BaseActivity 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.extensions.getParcelableArrayListExtraProvider -import com.nextcloud.talk.components.SetupSystemBars import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser import com.nextcloud.talk.utils.bundle.BundleKeys import javax.inject.Inject @@ -64,11 +64,11 @@ class ContactsActivity : BaseActivity() { MaterialTheme( colorScheme = colorScheme ) { + ColoredStatusBar() ContactsScreen( contactsViewModel = contactsViewModel, uiState = uiState.value ) - SetupSystemBars() } } } diff --git a/app/src/main/java/com/nextcloud/talk/contacts/ContactsScreen.kt b/app/src/main/java/com/nextcloud/talk/contacts/ContactsScreen.kt index 172dd04b3..f6a28074d 100644 --- a/app/src/main/java/com/nextcloud/talk/contacts/ContactsScreen.kt +++ b/app/src/main/java/com/nextcloud/talk/contacts/ContactsScreen.kt @@ -11,16 +11,18 @@ package com.nextcloud.talk.contacts import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource -import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle 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.ContactsSearchAppBar import com.nextcloud.talk.contacts.components.ConversationCreationOptions @Composable @@ -32,35 +34,37 @@ fun ContactsScreen(contactsViewModel: ContactsViewModel, uiState: ContactsUiStat val enableAddButton by contactsViewModel.enableAddButton.collectAsStateWithLifecycle() Scaffold( + modifier = Modifier + .statusBarsPadding(), topBar = { - AppBar( - title = stringResource(R.string.nc_app_product_name), - searchQuery = searchQuery, - isSearchActive = isSearchActive, - isAddParticipants = isAddParticipants, - autocompleteUsers = autocompleteUsers, - onEnableSearch = { - contactsViewModel.setSearchActive(true) - }, - onDisableSearch = { - contactsViewModel.setSearchActive(false) - }, - onUpdateSearchQuery = { - contactsViewModel.updateSearchQuery(query = it) - }, - onUpdateAutocompleteUsers = { - contactsViewModel.getContactsFromSearchParams() - }, - enableAddButton = enableAddButton, - clickAddButton = { - contactsViewModel.modifyClickAddButton(it) - } - ) + if (isSearchActive) { + ContactsSearchAppBar( + searchQuery = searchQuery, + onTextChange = { + contactsViewModel.updateSearchQuery(it) + contactsViewModel.getContactsFromSearchParams() + }, + onCloseSearch = { + contactsViewModel.updateSearchQuery("") + contactsViewModel.setSearchActive(false) + contactsViewModel.getContactsFromSearchParams() + }, + enableAddButton = enableAddButton, + isAddParticipants = isAddParticipants, + clickAddButton = { contactsViewModel.modifyClickAddButton(true) } + ) + } else { + ContactsAppBar( + isAddParticipants = isAddParticipants, + autocompleteUsers = autocompleteUsers, + onStartSearch = { contactsViewModel.setSearchActive(true) } + ) + } }, - content = { + content = { paddingValues -> Column( Modifier - .padding(it) + .padding(0.dp, paddingValues.calculateTopPadding(), 0.dp, 0.dp) .background(colorResource(id = R.color.bg_default)) ) { if (!isAddParticipants) { diff --git a/app/src/main/java/com/nextcloud/talk/contacts/components/AppBar.kt b/app/src/main/java/com/nextcloud/talk/contacts/components/AppBar.kt deleted file mode 100644 index 0e3b709ea..000000000 --- a/app/src/main/java/com/nextcloud/talk/contacts/components/AppBar.kt +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Nextcloud Talk - Android Client - * - * SPDX-FileCopyrightText: 2024 Sowjanya Kota - * SPDX-FileCopyrightText: 2025 Marcel Hibbe - * 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, - 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)) - } - } - } - } -} diff --git a/app/src/main/java/com/nextcloud/talk/contacts/components/ContactsAppBar.kt b/app/src/main/java/com/nextcloud/talk/contacts/components/ContactsAppBar.kt new file mode 100644 index 000000000..8b916e28d --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/contacts/components/ContactsAppBar.kt @@ -0,0 +1,77 @@ +/* + * Nextcloud Talk - Android Client + * + * SPDX-FileCopyrightText: 2024 Sowjanya Kota + * SPDX-FileCopyrightText: 2025 Marcel Hibbe + * 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, 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() + } + ) + } + } + } + ) +} diff --git a/app/src/main/java/com/nextcloud/talk/contacts/components/ContactsItem.kt b/app/src/main/java/com/nextcloud/talk/contacts/components/ContactsItem.kt index d87b5dc41..1fae754a5 100644 --- a/app/src/main/java/com/nextcloud/talk/contacts/components/ContactsItem.kt +++ b/app/src/main/java/com/nextcloud/talk/contacts/components/ContactsItem.kt @@ -15,7 +15,6 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.HorizontalDivider @@ -44,9 +43,13 @@ fun ContactsItem(contacts: List, contactsViewModel: ContactsVi } LazyColumn( modifier = Modifier - .padding(8.dp) .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) ) { groupedContacts.forEach { (initial, contactsForInitial) -> diff --git a/app/src/main/java/com/nextcloud/talk/contacts/components/ContactsSearchAppBar.kt b/app/src/main/java/com/nextcloud/talk/contacts/components/ContactsSearchAppBar.kt new file mode 100644 index 000000000..324b95592 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/contacts/components/ContactsSearchAppBar.kt @@ -0,0 +1,104 @@ +/* + * Nextcloud Talk - Android Client + * + * SPDX-FileCopyrightText: 2024 Sowjanya Kota + * SPDX-FileCopyrightText: 2025 Marcel Hibbe + * 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() + } + } + ) diff --git a/app/src/main/java/com/nextcloud/talk/contacts/components/SearchComponent.kt b/app/src/main/java/com/nextcloud/talk/contacts/components/SearchComponent.kt deleted file mode 100644 index 8e79c0484..000000000 --- a/app/src/main/java/com/nextcloud/talk/contacts/components/SearchComponent.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Nextcloud Talk - Android Client - * - * SPDX-FileCopyrightText: 2025 Julius Linus - * 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() - } - } - ) diff --git a/app/src/main/java/com/nextcloud/talk/conversationcreation/ConversationCreationActivity.kt b/app/src/main/java/com/nextcloud/talk/conversationcreation/ConversationCreationActivity.kt index 215ffde5f..c6b5a14c8 100644 --- a/app/src/main/java/com/nextcloud/talk/conversationcreation/ConversationCreationActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/conversationcreation/ConversationCreationActivity.kt @@ -84,8 +84,8 @@ import com.nextcloud.talk.R import com.nextcloud.talk.activities.BaseActivity import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.chat.ChatActivity +import com.nextcloud.talk.components.ColoredStatusBar import com.nextcloud.talk.contacts.ContactsActivity -import com.nextcloud.talk.components.SetupSystemBars import com.nextcloud.talk.contacts.loadImage import com.nextcloud.talk.extensions.getParcelableArrayListExtraProvider import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser @@ -117,7 +117,6 @@ class ConversationCreationActivity : BaseActivity() { colorScheme = colorScheme ) { ConversationCreationScreen(conversationCreationViewModel, context, pickImage) - SetupSystemBars() } } } @@ -172,6 +171,7 @@ fun ConversationCreationScreen( } ) + ColoredStatusBar() Scaffold( topBar = { TopAppBar( @@ -191,7 +191,7 @@ fun ConversationCreationScreen( content = { paddingValues -> Column( modifier = Modifier - .padding(paddingValues) + .padding(0.dp, paddingValues.calculateTopPadding(), 0.dp, 0.dp) .background(colorResource(id = R.color.bg_default)) .fillMaxSize() .verticalScroll(rememberScrollState()) diff --git a/app/src/main/java/com/nextcloud/talk/conversationinfo/ConversationInfoActivity.kt b/app/src/main/java/com/nextcloud/talk/conversationinfo/ConversationInfoActivity.kt index 0ac8e5097..08e97f91d 100644 --- a/app/src/main/java/com/nextcloud/talk/conversationinfo/ConversationInfoActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/conversationinfo/ConversationInfoActivity.kt @@ -190,7 +190,7 @@ class ConversationInfoActivity : binding = ActivityConversationInfoBinding.inflate(layoutInflater) setupActionBar() setContentView(binding.root) - setupSystemColors() + initSystemBars() viewModel = ViewModelProvider(this, viewModelFactory)[ConversationInfoViewModel::class.java] diff --git a/app/src/main/java/com/nextcloud/talk/conversationinfoedit/ConversationInfoEditActivity.kt b/app/src/main/java/com/nextcloud/talk/conversationinfoedit/ConversationInfoEditActivity.kt index 47e007a06..6af3850e3 100644 --- a/app/src/main/java/com/nextcloud/talk/conversationinfoedit/ConversationInfoEditActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/conversationinfoedit/ConversationInfoEditActivity.kt @@ -99,7 +99,7 @@ class ConversationInfoEditActivity : BaseActivity() { binding = ActivityConversationInfoEditBinding.inflate(layoutInflater) setupActionBar() setContentView(binding.root) - setupSystemColors() + initSystemBars() val extras: Bundle? = intent.extras diff --git a/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt b/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt index 3bf0610d5..3c50dbbfa 100644 --- a/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/conversationlist/ConversationsListActivity.kt @@ -81,6 +81,7 @@ import com.nextcloud.talk.adapters.items.GenericTextHeaderItem import com.nextcloud.talk.adapters.items.LoadMoreResultsItem import com.nextcloud.talk.adapters.items.MessageResultItem import com.nextcloud.talk.adapters.items.MessagesTextHeaderItem +import com.nextcloud.talk.adapters.items.SpacerItem import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager @@ -266,7 +267,7 @@ class ConversationsListActivity : binding = ActivityConversationsBinding.inflate(layoutInflater) setupActionBar() setContentView(binding.root) - setupSystemColors() + initSystemBars() viewThemeUtils.material.themeCardView(binding.searchToolbar) viewThemeUtils.material.themeSearchBarText(binding.searchText) @@ -293,10 +294,9 @@ class ConversationsListActivity : override fun onResume() { super.onResume() - - // actionBar?.show() if (adapter == null) { adapter = FlexibleAdapter(conversationItems, this, true) + addEmptyItemForEdgeToEdgeIfNecessary() } else { binding.loadingContent.visibility = View.GONE } @@ -342,6 +342,14 @@ class ConversationsListActivity : 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") private fun initObservers() { this.lifecycleScope.launch { @@ -963,8 +971,7 @@ class ConversationsListActivity : } else { showToolbar() } - colorizeStatusBar() - colorizeNavigationBar() + initSystemBars() } } diff --git a/app/src/main/java/com/nextcloud/talk/diagnose/DiagnoseActivity.kt b/app/src/main/java/com/nextcloud/talk/diagnose/DiagnoseActivity.kt index c2dcf88fa..02426b3f7 100644 --- a/app/src/main/java/com/nextcloud/talk/diagnose/DiagnoseActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/diagnose/DiagnoseActivity.kt @@ -21,6 +21,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.runtime.collectAsState @@ -28,8 +29,9 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.ui.Modifier import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource -import androidx.lifecycle.ViewModelProvider +import androidx.compose.ui.unit.dp import androidx.core.net.toUri +import androidx.lifecycle.ViewModelProvider import autodagger.AutoInjector import com.nextcloud.talk.BuildConfig 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.application.NextcloudTalkApplication import com.nextcloud.talk.arbitrarystorage.ArbitraryStorageManager +import com.nextcloud.talk.components.ColoredStatusBar import com.nextcloud.talk.components.StandardAppBar -import com.nextcloud.talk.components.SetupSystemBars import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.utils.BrandingUtils import com.nextcloud.talk.utils.ClosedInterfaceImpl @@ -109,18 +111,22 @@ class DiagnoseActivity : BaseActivity() { MaterialTheme( colorScheme = colorScheme ) { + ColoredStatusBar() Scaffold( + modifier = Modifier + .statusBarsPadding(), topBar = { StandardAppBar( title = stringResource(R.string.nc_settings_diagnose_title), menuItems ) }, - content = { + content = { paddingValues -> val viewState = diagnoseViewModel.notificationViewState.collectAsState().value + Column( Modifier - .padding(it) + .padding(0.dp, paddingValues.calculateTopPadding(), 0.dp, 0.dp) .background(backgroundColor) .fillMaxSize() ) { @@ -136,7 +142,6 @@ class DiagnoseActivity : BaseActivity() { } } ) - SetupSystemBars() } } } diff --git a/app/src/main/java/com/nextcloud/talk/diagnose/DiagnoseContentComposable.kt b/app/src/main/java/com/nextcloud/talk/diagnose/DiagnoseContentComposable.kt index f6cfba19e..d3cc1b495 100644 --- a/app/src/main/java/com/nextcloud/talk/diagnose/DiagnoseContentComposable.kt +++ b/app/src/main/java/com/nextcloud/talk/diagnose/DiagnoseContentComposable.kt @@ -65,7 +65,12 @@ fun DiagnoseContentComposable( Column( modifier = Modifier .fillMaxSize() - .padding(16.dp) + .padding( + start = 16.dp, + top = 0.dp, + end = 16.dp, + bottom = 0.dp + ) .verticalScroll(rememberScrollState()) ) { data.value.forEach { element -> @@ -100,6 +105,7 @@ fun DiagnoseContentComposable( ShowTestPushButton(onTestPushClick) } ShowNotificationData(isLoading, showDialog, context, viewState, onDismissDialog) + Spacer(modifier = Modifier.height(40.dp)) } } diff --git a/app/src/main/java/com/nextcloud/talk/invitation/InvitationsActivity.kt b/app/src/main/java/com/nextcloud/talk/invitation/InvitationsActivity.kt index 3f1c60650..40cfc61f3 100644 --- a/app/src/main/java/com/nextcloud/talk/invitation/InvitationsActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/invitation/InvitationsActivity.kt @@ -65,7 +65,7 @@ class InvitationsActivity : BaseActivity() { binding = ActivityInvitationsBinding.inflate(layoutInflater) setupActionBar() setContentView(binding.root) - setupSystemColors() + initSystemBars() adapter = InvitationsAdapter(currentUser) { invitation, action -> handleInvitation(invitation, action) diff --git a/app/src/main/java/com/nextcloud/talk/location/GeocodingActivity.kt b/app/src/main/java/com/nextcloud/talk/location/GeocodingActivity.kt index 33605a6ea..c4fcc694e 100644 --- a/app/src/main/java/com/nextcloud/talk/location/GeocodingActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/location/GeocodingActivity.kt @@ -67,7 +67,7 @@ class GeocodingActivity : binding = ActivityGeocodingBinding.inflate(layoutInflater) setupActionBar() setContentView(binding.root) - setupSystemColors() + initSystemBars() Configuration.getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context)) diff --git a/app/src/main/java/com/nextcloud/talk/location/LocationPickerActivity.kt b/app/src/main/java/com/nextcloud/talk/location/LocationPickerActivity.kt index 569a1a269..339f46ca2 100644 --- a/app/src/main/java/com/nextcloud/talk/location/LocationPickerActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/location/LocationPickerActivity.kt @@ -129,7 +129,7 @@ class LocationPickerActivity : binding = ActivityLocationBinding.inflate(layoutInflater) setupActionBar() setContentView(binding.root) - setupSystemColors() + initSystemBars() getInstance().load(context, PreferenceManager.getDefaultSharedPreferences(context)) diff --git a/app/src/main/java/com/nextcloud/talk/messagesearch/MessageSearchActivity.kt b/app/src/main/java/com/nextcloud/talk/messagesearch/MessageSearchActivity.kt index f32e54193..7e9bae5b3 100644 --- a/app/src/main/java/com/nextcloud/talk/messagesearch/MessageSearchActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/messagesearch/MessageSearchActivity.kt @@ -70,7 +70,7 @@ class MessageSearchActivity : BaseActivity() { binding = ActivityMessageSearchBinding.inflate(layoutInflater) setupActionBar() setContentView(binding.root) - setupSystemColors() + initSystemBars() viewModel = ViewModelProvider(this, viewModelFactory)[MessageSearchViewModel::class.java] user = currentUserProvider.currentUser.blockingGet() diff --git a/app/src/main/java/com/nextcloud/talk/openconversations/ListOpenConversationsActivity.kt b/app/src/main/java/com/nextcloud/talk/openconversations/ListOpenConversationsActivity.kt index 986ff8b9a..9ceea142f 100644 --- a/app/src/main/java/com/nextcloud/talk/openconversations/ListOpenConversationsActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/openconversations/ListOpenConversationsActivity.kt @@ -57,7 +57,7 @@ class ListOpenConversationsActivity : BaseActivity() { binding = ActivityOpenConversationsBinding.inflate(layoutInflater) setupActionBar() setContentView(binding.root) - setupSystemColors() + initSystemBars() viewThemeUtils.platform.colorImageView(binding.searchOpenConversations, ColorRole.ON_SURFACE) viewThemeUtils.material.colorTextInputLayout(binding.textInputLayout) diff --git a/app/src/main/java/com/nextcloud/talk/profile/ProfileActivity.kt b/app/src/main/java/com/nextcloud/talk/profile/ProfileActivity.kt index 1333178fc..facf47ef6 100644 --- a/app/src/main/java/com/nextcloud/talk/profile/ProfileActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/profile/ProfileActivity.kt @@ -119,7 +119,7 @@ class ProfileActivity : BaseActivity() { binding = ActivityProfileBinding.inflate(layoutInflater) setupActionBar() setContentView(binding.root) - setupSystemColors() + initSystemBars() } override fun onResume() { diff --git a/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt b/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt index 73b88bbfb..9dad6eec4 100644 --- a/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/settings/SettingsActivity.kt @@ -145,7 +145,7 @@ class SettingsActivity : binding = ActivitySettingsBinding.inflate(layoutInflater) setupActionBar() setContentView(binding.root) - setupSystemColors() + initSystemBars() binding.avatarImage.let { ViewCompat.setTransitionName(it, "userAvatar.transitionTag") } diff --git a/app/src/main/java/com/nextcloud/talk/shareditems/activities/SharedItemsActivity.kt b/app/src/main/java/com/nextcloud/talk/shareditems/activities/SharedItemsActivity.kt index 021cb9faa..66855ed18 100644 --- a/app/src/main/java/com/nextcloud/talk/shareditems/activities/SharedItemsActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/shareditems/activities/SharedItemsActivity.kt @@ -13,7 +13,6 @@ import android.os.Bundle import android.util.Log import android.view.MenuItem import android.view.View -import androidx.core.content.res.ResourcesCompat import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.GridLayoutManager 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.model.SharedItemType 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_ROOM_TOKEN import javax.inject.Inject @@ -57,15 +55,11 @@ class SharedItemsActivity : BaseActivity() { setSupportActionBar(binding.sharedItemsToolbar) setContentView(binding.root) - viewThemeUtils.platform.themeStatusBar(this) + initSystemBars() + viewThemeUtils.material.themeToolbar(binding.sharedItemsToolbar) viewThemeUtils.material.themeTabLayoutOnSurface(binding.sharedItemsTabs) - DisplayUtils.applyColorToNavigationBar( - this.window, - ResourcesCompat.getColor(resources, R.color.bg_default, null) - ) - supportActionBar?.title = conversationName supportActionBar?.setDisplayHomeAsUpEnabled(true) diff --git a/app/src/main/java/com/nextcloud/talk/translate/ui/TranslateActivity.kt b/app/src/main/java/com/nextcloud/talk/translate/ui/TranslateActivity.kt index 04758b847..8817d7ccb 100644 --- a/app/src/main/java/com/nextcloud/talk/translate/ui/TranslateActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/translate/ui/TranslateActivity.kt @@ -86,7 +86,7 @@ class TranslateActivity : BaseActivity() { } setupActionBar() setContentView(binding.root) - setupSystemColors() + initSystemBars() setupTextViews() viewModel.getLanguages() setupCopyButton() diff --git a/app/src/main/java/com/nextcloud/talk/utils/AppCompatActivityExtensions.kt b/app/src/main/java/com/nextcloud/talk/utils/AppCompatActivityExtensions.kt new file mode 100644 index 000000000..982c27355 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/utils/AppCompatActivityExtensions.kt @@ -0,0 +1,38 @@ +/* + * Nextcloud Talk - Android Client + * + * SPDX-FileCopyrightText: 2025 Marcel Hibbe + * 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) +} diff --git a/app/src/main/res/layout/activity_chat.xml b/app/src/main/res/layout/activity_chat.xml index 0a77d7a5e..c55d38edd 100644 --- a/app/src/main/res/layout/activity_chat.xml +++ b/app/src/main/res/layout/activity_chat.xml @@ -91,6 +91,7 @@ + + android:padding="@dimen/standard_half_padding"> + android:padding="@dimen/standard_half_padding"> + android:padding="@dimen/standard_half_padding"> + diff --git a/app/src/main/res/layout/activity_conversations.xml b/app/src/main/res/layout/activity_conversations.xml index 6c69b1207..05a89562a 100644 --- a/app/src/main/res/layout/activity_conversations.xml +++ b/app/src/main/res/layout/activity_conversations.xml @@ -292,7 +292,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" - android:layout_margin="16dp" + android:layout_marginEnd="16dp" + android:layout_marginBottom="36dp" android:contentDescription="@string/nc_new_conversation" app:borderWidth="0dp" app:srcCompat="@drawable/ic_pencil_grey600_24dp" diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 28d31573a..d3bbd1bf6 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -906,6 +906,9 @@ + \ No newline at end of file diff --git a/app/src/main/res/layout/item_spacer.xml b/app/src/main/res/layout/item_spacer.xml new file mode 100644 index 000000000..d68a36408 --- /dev/null +++ b/app/src/main/res/layout/item_spacer.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 7c9821c63..83ca98dec 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -29,6 +29,9 @@ @style/ChatSendButtonMenu @dimen/dialogBorderRadius @color/bg_default + + +