Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import com.nextcloud.utils.extensions.lastFragment
import com.nextcloud.utils.extensions.logFileSize
import com.nextcloud.utils.extensions.navigateToAllFiles
import com.nextcloud.utils.extensions.observeWorker
import com.nextcloud.utils.extensions.setVisibleIf
import com.nextcloud.utils.fileNameValidator.FileNameValidator.checkFolderPath
import com.nextcloud.utils.view.FastScrollUtils
import com.owncloud.android.MainApp
Expand Down Expand Up @@ -481,10 +482,9 @@ class FileDisplayActivity :
val result = GetNotificationsRemoteOperation()
.execute(clientFactory.createNextcloudClient(accountManager.user))

if (result.isSuccess && result.getResultData()?.isEmpty() == false) {
runOnUiThread { mNotificationButton.visibility = View.VISIBLE }
} else {
runOnUiThread { mNotificationButton.visibility = View.GONE }
val isVisible = (result.isSuccess && result.getResultData()?.isEmpty() == false)
withContext(Dispatchers.Main) {
mNotificationButton.setVisibleIf(isVisible)
}
} catch (_: CreationException) {
Log_OC.e(TAG, "Could not fetch notifications!")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import android.content.Intent
import android.graphics.Typeface
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.TextUtils
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.view.Gravity
Expand Down Expand Up @@ -91,7 +90,7 @@ class NotificationListAdapter(

private fun bindSubject(holder: NotificationViewHolder, notification: Notification) {
val file = notification.subjectRichParameters[FILE]
if (file == null && !TextUtils.isEmpty(notification.getLink())) {
if (file == null && !notification.getLink().isNullOrEmpty()) {
val subject = "${notification.getSubject()} ↗"
holder.binding.subject.run {
setTypeface(typeface, Typeface.BOLD)
Expand All @@ -102,7 +101,7 @@ class NotificationListAdapter(
}
} else {
holder.binding.subject.run {
text = if (!TextUtils.isEmpty(notification.subjectRich)) {
text = if (!notification.subjectRich.isNullOrEmpty()) {
makeSpecialPartsBold(notification)
} else {
notification.getSubject()
Expand Down Expand Up @@ -139,14 +138,16 @@ class NotificationListAdapter(

private fun colorViewHolder(holder: NotificationViewHolder) {
viewThemeUtils.platform.run {
colorImageView(holder.binding.icon, ColorRole.ON_SURFACE_VARIANT)
colorImageView(holder.binding.dismiss, ColorRole.ON_SURFACE_VARIANT)
colorTextView(holder.binding.subject, ColorRole.ON_SURFACE)
colorTextView(holder.binding.message, ColorRole.ON_SURFACE_VARIANT)
colorTextView(holder.binding.datetime, ColorRole.ON_SURFACE_VARIANT)
holder.binding.run {
colorImageView(icon, ColorRole.ON_SURFACE_VARIANT)
colorTextView(subject, ColorRole.ON_SURFACE)
colorTextView(message, ColorRole.ON_SURFACE_VARIANT)
colorTextView(datetime, ColorRole.ON_SURFACE_VARIANT)
}
}
}

viewThemeUtils.material.colorMaterialButtonContent(holder.binding.dismiss, ColorRole.ON_SURFACE)
}
// endregion

// region Button binding
Expand Down Expand Up @@ -271,17 +272,16 @@ class NotificationListAdapter(
// endregion

// region Data manipulation

@SuppressLint("NotifyDataSetChanged")
fun setNotificationItems(notificationItems: List<Notification>) {
notificationsList.clear()
notificationsList.addAll(notificationItems)
notifyDataSetChanged()
}

fun removeNotification(holder: NotificationViewHolder) {
val position = holder.bindingAdapterPosition
if (position in 0 until notificationsList.size) {
fun removeNotification(id: Int) {
val position = notificationsList.indexOfFirst { it.notificationId == id }
if (position != -1) {
notificationsList.removeAt(position)
notifyItemRemoved(position)
notifyItemRangeChanged(position, notificationsList.size)
Expand All @@ -299,7 +299,6 @@ class NotificationListAdapter(
holder.binding.buttons.getChildAt(i).isEnabled = enabled
}
}

// endregion

private fun makeSpecialPartsBold(notification: Notification): SpannableStringBuilder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class NotificationExecuteActionTask(
performRequest(action)
}

fragment.onActionCallback(isSuccess, notification, holder)
fragment.onNotificationActionCompletion(isSuccess, notification, holder)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ class NotificationsFragment :
if (item.itemId != R.id.action_empty_notifications) return false
lifecycleScope.launch(Dispatchers.IO) {
val result = DeleteAllNotificationsRemoteOperation().execute(client)
withContext(Dispatchers.Main) { onRemovedAllNotifications(result.isSuccess) }
withContext(Dispatchers.Main) { removeAllNotifications(result.isSuccess) }
}
return true
}
Expand Down Expand Up @@ -271,7 +271,6 @@ class NotificationsFragment :
// region Data loading
private fun fetchAndSetData(client: NextcloudClient) {
lifecycleScope.launch(Dispatchers.IO) {
initializeAdapter()
val result = GetNotificationsRemoteOperation().execute(client)
withContext(Dispatchers.Main) {
state = when {
Expand Down Expand Up @@ -323,21 +322,20 @@ class NotificationsFragment :
}

// region Callbacks
override fun onRemovedNotification(isSuccess: Boolean, client: NextcloudClient) {
if (!isSuccess) {
override fun removeNotification(id: Int, success: Boolean, client: NextcloudClient) {
if (success) {
adapter?.removeNotification(id)
if (adapter?.itemCount == 0) {
state = NotificationsUIState.Empty
}
} else {
DisplayUtils.showSnackMessage(requireActivity(), getString(R.string.remove_notification_failed))
fetchAndSetData(client)
}
}

override fun removeNotification(holder: NotificationListAdapter.NotificationViewHolder) {
adapter?.removeNotification(holder)
if (adapter?.itemCount == 0) {
state = NotificationsUIState.Empty
}
fetchAndSetData(client)
}

override fun onRemovedAllNotifications(isSuccess: Boolean) {
override fun removeAllNotifications(isSuccess: Boolean) {
if (isSuccess) {
adapter?.removeAllNotifications()
state = NotificationsUIState.Empty
Expand All @@ -346,13 +344,14 @@ class NotificationsFragment :
}
}

override fun onActionCallback(
override fun onNotificationActionCompletion(
isSuccess: Boolean,
notification: Notification,
holder: NotificationListAdapter.NotificationViewHolder
) {
// after any action successfully completed remove the notification
if (isSuccess) {
adapter?.removeNotification(holder)
adapter?.removeNotification(notification.notificationId)
} else {
adapter?.bindButtons(holder, notification)
DisplayUtils.showSnackMessage(requireActivity(), getString(R.string.notification_action_failed))
Expand All @@ -379,7 +378,7 @@ class NotificationsFragment :
lifecycleScope.launch(Dispatchers.IO) {
val result = DeleteNotificationRemoteOperation(id).execute(client)
withContext(Dispatchers.Main) {
onRemovedNotification(result?.isSuccess == true, client)
removeNotification(id, success = (result?.isSuccess == true), client)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2019 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH
* SPDX-License-Identifier: AGPL-3.0-or-later OR GPL-2.0-only
Expand All @@ -13,12 +14,14 @@ import com.owncloud.android.ui.adapter.NotificationListAdapter.NotificationViewH

interface NotificationsContract {
interface View {
fun onRemovedNotification(isSuccess: Boolean, client: NextcloudClient)
fun removeNotification(id: Int, success: Boolean, client: NextcloudClient)

fun removeNotification(holder: NotificationViewHolder)
fun removeAllNotifications(isSuccess: Boolean)

fun onRemovedAllNotifications(isSuccess: Boolean)

fun onActionCallback(isSuccess: Boolean, notification: Notification, holder: NotificationViewHolder)
fun onNotificationActionCompletion(
isSuccess: Boolean,
notification: Notification,
holder: NotificationViewHolder
)
}
}
125 changes: 66 additions & 59 deletions app/src/main/res/layout/notification_list_item.xml
Original file line number Diff line number Diff line change
@@ -1,87 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Nextcloud - Android Client
~
~ SPDX-FileCopyrightText: 2018-2024 Nextcloud GmbH and Nextcloud contributors
~ SPDX-FileCopyrightText: 2018-2026 Nextcloud GmbH and Nextcloud contributors
~ SPDX-FileCopyrightText: 2026 Alper Ozturk <alper.ozturk@nextcloud.com>
~ SPDX-FileCopyrightText: 2023 Andy Scherzinger <info@andy-scherzinger.de>
~ SPDX-FileCopyrightText: 2023 TSI-mc
~ SPDX-FileCopyrightText: 2018 Tobias Kaminsky <tobias@kaminsky.me>
~ SPDX-License-Identifier: GPL-3.0-or-later AND AGPL-3.0-or-later
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:paddingStart="@dimen/standard_padding"
android:paddingTop="@dimen/standard_padding"
android:paddingEnd="@dimen/standard_padding"
android:paddingBottom="@dimen/standard_padding"
tools:ignore="UseCompoundDrawables">
android:paddingBottom="@dimen/standard_padding">

<ImageView
android:id="@+id/icon"
android:layout_width="@dimen/notification_icon_width"
android:layout_height="@dimen/notification_icon_height"
android:layout_marginEnd="@dimen/notification_icon_layout_right_end_margin"
android:contentDescription="@string/notification_icon"
android:src="@drawable/ic_notification" />
android:src="@drawable/ic_notification"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<LinearLayout
android:id="@+id/notification_content"
<com.google.android.material.button.MaterialButton
android:id="@+id/dismiss"
style="@style/Widget.Material3.Button.IconButton"
android:layout_width="@dimen/minimum_size_for_touchable_area"
android:layout_height="@dimen/minimum_size_for_touchable_area"
android:contentDescription="@string/dismiss_notification_description"
app:icon="@drawable/ic_close"
app:iconPadding="@dimen/minimum_size_for_touchable_area_icon_padding"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/subject"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
android:layout_marginStart="@dimen/notification_icon_layout_right_end_margin"
android:ellipsize="end"
android:paddingBottom="@dimen/standard_half_padding"
android:textAppearance="?attr/textAppearanceTitleSmall"
android:textColor="@color/text_color"
app:layout_constraintEnd_toStartOf="@id/dismiss"
app:layout_constraintStart_toEndOf="@id/icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="@string/placeholder_filename" />

<TextView
android:id="@+id/subject"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:ellipsize="end"
android:paddingBottom="@dimen/standard_half_padding"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="@color/text_color"
android:textSize="@dimen/txt_size_16sp"
tools:text="@string/placeholder_filename" />

<TextView
android:id="@+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:paddingBottom="@dimen/standard_quarter_padding"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="@color/secondary_text_color"
android:textSize="@dimen/txt_size_14sp"
tools:text="@string/placeholder_sentence" />

<TextView
android:id="@+id/datetime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:textColor="@color/secondary_text_color"
android:textSize="@dimen/text_size_13sp"
tools:text="@string/placeholder_sentence" />

<LinearLayout
android:id="@+id/buttons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/standard_quarter_margin"
android:layout_marginEnd="@dimen/notification_list_item_grid_layout_left_start_margin"
android:columnCount="3"
android:gravity="start"
android:orientation="horizontal" />
<TextView
android:id="@+id/message"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/notification_icon_layout_right_end_margin"
android:ellipsize="end"
android:paddingBottom="@dimen/standard_quarter_padding"
android:textAppearance="?attr/textAppearanceBodyMedium"
android:textColor="@color/secondary_text_color"
app:layout_constraintEnd_toStartOf="@id/dismiss"
app:layout_constraintStart_toEndOf="@id/icon"
app:layout_constraintTop_toBottomOf="@id/subject"
tools:text="@string/placeholder_sentence" />

</LinearLayout>
<TextView
android:id="@+id/datetime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/notification_icon_layout_right_end_margin"
android:ellipsize="end"
android:textAppearance="?attr/textAppearanceBodySmall"
android:textColor="@color/secondary_text_color"
app:layout_constraintEnd_toStartOf="@id/dismiss"
app:layout_constraintStart_toEndOf="@id/icon"
app:layout_constraintTop_toBottomOf="@id/message"
tools:text="@string/placeholder_sentence" />

<ImageView
android:id="@+id/dismiss"
android:layout_width="wrap_content"
<LinearLayout
android:id="@+id/buttons"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:contentDescription="@string/dismiss_notification_description"
android:src="@drawable/ic_close" />
android:layout_marginStart="@dimen/notification_icon_layout_right_end_margin"
android:layout_marginTop="@dimen/standard_quarter_margin"
android:gravity="start"
android:orientation="horizontal"
app:layout_constraintEnd_toStartOf="@id/dismiss"
app:layout_constraintStart_toEndOf="@id/icon"
app:layout_constraintTop_toBottomOf="@id/datetime" />

</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
4 changes: 3 additions & 1 deletion app/src/main/res/layout/toolbar_standard.xml
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,9 @@
app:iconTint="@color/fontAppbar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/switch_account_button"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent"
android:visibility="gone"
tools:visibility="visible" />

</LinearLayout>

Expand Down
Loading