diff --git a/WordPress/src/main/java/org/wordpress/android/models/NoteExtensions.kt b/WordPress/src/main/java/org/wordpress/android/models/NoteExtensions.kt index 47b9159e7530..6685cfffb715 100644 --- a/WordPress/src/main/java/org/wordpress/android/models/NoteExtensions.kt +++ b/WordPress/src/main/java/org/wordpress/android/models/NoteExtensions.kt @@ -1,15 +1,28 @@ package org.wordpress.android.models +import org.wordpress.android.models.Notification.PostNotification.Like +import org.wordpress.android.models.Notification.PostNotification.Reblog +import org.wordpress.android.models.Notification.PostNotification.NewPost + val Note.type get() = NoteType.from(rawType) sealed class Notification { - data class Like(val url: String, val title: String): Notification() + sealed class PostNotification: Notification() { + abstract val url: String + abstract val title: String + data class Like(override val url: String, override val title: String): PostNotification() + data class Reblog(override val url: String, override val title: String): PostNotification() + data class NewPost(override val url: String, override val title: String): PostNotification() + } + data object Comment: Notification() data object Unknown: Notification() companion object { fun from(rawNote: Note) = when(rawNote.type) { - NoteType.Like -> Like(url= rawNote.url, title = rawNote.title) + NoteType.Like -> Like(url = rawNote.url, title = rawNote.title) + NoteType.Reblog -> Reblog(url= rawNote.url, title = rawNote.title) + NoteType.NewPost -> NewPost(url= rawNote.url, title = rawNote.title) else -> Unknown } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsListFragmentPage.kt b/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsListFragmentPage.kt index 35fc491b89d4..1948ca3ccf90 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsListFragmentPage.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsListFragmentPage.kt @@ -10,11 +10,15 @@ import android.view.animation.Animation.AnimationListener import androidx.annotation.StringRes import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels -import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.flowWithLifecycle +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.OnScrollListener import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode.MAIN @@ -45,6 +49,8 @@ import org.wordpress.android.ui.notifications.NotificationsListFragment.Companio import org.wordpress.android.ui.notifications.NotificationsListFragment.Companion.TabPosition.Follow import org.wordpress.android.ui.notifications.NotificationsListFragment.Companion.TabPosition.Like import org.wordpress.android.ui.notifications.NotificationsListFragment.Companion.TabPosition.Unread +import org.wordpress.android.ui.notifications.NotificationsListViewModel.InlineActionEvent +import org.wordpress.android.ui.notifications.NotificationsListViewModel.InlineActionEvent.SharePostButtonTapped import org.wordpress.android.ui.notifications.adapters.NotesAdapter import org.wordpress.android.ui.notifications.adapters.NotesAdapter.DataLoadedListener import org.wordpress.android.ui.notifications.adapters.NotesAdapter.FILTERS @@ -404,12 +410,27 @@ class NotificationsListFragmentPage : ViewPagerFragment(R.layout.notifications_l } private fun createOrGetNotesAdapter(): NotesAdapter { - return notesAdapter ?: NotesAdapter(requireActivity(), this, null).apply { + return notesAdapter ?: NotesAdapter( requireActivity(), this, null, + inlineActionEvents = viewModel.inlineActionEvents).apply { notesAdapter = this this.setOnNoteClickListener(mOnNoteClickListener) + viewModel.inlineActionEvents.flowWithLifecycle(viewLifecycleOwner.lifecycle, Lifecycle.State.STARTED) + .onEach(::handleInlineActionEvent) + .launchIn(viewLifecycleOwner.lifecycleScope) } } + private fun handleInlineActionEvent(actionEvent: InlineActionEvent) { + when (actionEvent) { + is SharePostButtonTapped -> actionEvent.notification.let { postNotification -> + context?.let { + ActivityLauncher.openShareIntent(it, postNotification.url, postNotification.title) + } + } + } + } + + /** * Mark notifications as read in CURRENT tab, use filteredNotes instead of notes */ diff --git a/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsListViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsListViewModel.kt index 74fb7d442821..6299411f80d2 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsListViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsListViewModel.kt @@ -5,9 +5,11 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.flow.MutableSharedFlow import org.greenrobot.eventbus.EventBus import org.wordpress.android.datasets.NotificationsTable import org.wordpress.android.models.Note +import org.wordpress.android.models.Notification.PostNotification import org.wordpress.android.modules.UI_THREAD import org.wordpress.android.push.GCMMessageHandler import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureRemovalOverlayUtil @@ -36,6 +38,8 @@ class NotificationsListViewModel @Inject constructor( private val _showJetpackOverlay = MutableLiveData>() val showJetpackOverlay: LiveData> = _showJetpackOverlay + val inlineActionEvents = MutableSharedFlow() + val isNotificationsPermissionsWarningDismissed get() = appPrefsWrapper.notificationPermissionsWarningDismissed @@ -76,4 +80,8 @@ class NotificationsListViewModel @Inject constructor( EventBus.getDefault().post(NotificationsChanged()) } } + + sealed class InlineActionEvent { + data class SharePostButtonTapped(val notification: PostNotification): InlineActionEvent() + } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/notifications/adapters/NotesAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/notifications/adapters/NotesAdapter.kt index af54aee9c8a5..72aaa615a6c0 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/notifications/adapters/NotesAdapter.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/notifications/adapters/NotesAdapter.kt @@ -19,16 +19,23 @@ import androidx.core.text.BidiFormatter import androidx.core.view.ViewCompat import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.launch import org.wordpress.android.R import org.wordpress.android.WordPress import org.wordpress.android.datasets.NotificationsTable import org.wordpress.android.models.Note import org.wordpress.android.models.Note.NoteTimeGroup import org.wordpress.android.models.Note.TimeStampComparator -import org.wordpress.android.models.NoteType -import org.wordpress.android.models.type +import org.wordpress.android.models.Notification +import org.wordpress.android.models.Notification.Comment +import org.wordpress.android.models.Notification.PostNotification +import org.wordpress.android.models.Notification.Unknown import org.wordpress.android.ui.comments.CommentUtils import org.wordpress.android.ui.notifications.NotificationsListFragmentPage.OnNoteClickListener +import org.wordpress.android.ui.notifications.NotificationsListViewModel.InlineActionEvent import org.wordpress.android.ui.notifications.adapters.NotesAdapter.NoteViewHolder import org.wordpress.android.ui.notifications.blocks.NoteBlockClickableSpan import org.wordpress.android.ui.notifications.utils.NotificationsUtilsWrapper @@ -40,7 +47,8 @@ import javax.inject.Inject class NotesAdapter( context: Context, dataLoadedListener: DataLoadedListener, - onLoadMoreListener: OnLoadMoreListener? + onLoadMoreListener: OnLoadMoreListener?, + private val inlineActionEvents: MutableSharedFlow, ) : RecyclerView.Adapter() { private val avatarSize: Int private val textIndentSize: Int @@ -265,31 +273,6 @@ class NotesAdapter( private fun Note.shouldShowMultipleAvatars() = isFollowType || isLikeType || isCommentLikeType - @Suppress("ForbiddenComment") - private fun NoteViewHolder.bindInlineActionIconsForNote(note: Note) { - when (note.type) { - NoteType.Comment -> { - actionIcon.setImageResource(R.drawable.star_empty) - actionIcon.isVisible = true - actionIcon.setOnClickListener { - // TODO: handle tap on comment's inline action icon (the star) - } - } - NoteType.NewPost, - NoteType.Reblog, - NoteType.Like -> { - // TODO: Use the icon from the Figma design - actionIcon.setImageResource(R.drawable.gb_ic_share) - actionIcon.isVisible = true - actionIcon.setOnClickListener { - // TODO: handle tap on comment's inline action icon (the share icon) - } - } - else -> { - actionIcon.isVisible = false - } - } - } private fun handleMaxLines(subject: TextView, detail: TextView) { subject.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener { @@ -352,6 +335,8 @@ class NotesAdapter( val unreadNotificationView: View val actionIcon: ImageView + val coroutineScope = CoroutineScope(Dispatchers.Main) + init { contentView = checkNotNull(view.findViewById(R.id.note_content_container)) headerText = checkNotNull(view.findViewById(R.id.header_text)) @@ -370,6 +355,33 @@ class NotesAdapter( actionIcon = checkNotNull(view.findViewById(R.id.action)) contentView.setOnClickListener(onClickListener) } + + @Suppress("ForbiddenComment") + fun bindInlineActionIconsForNote(note: Note) = Notification.from(note).let { notification -> + when (notification) { + Comment -> { + actionIcon.setImageResource(R.drawable.star_empty) + actionIcon.isVisible = true + actionIcon.setOnClickListener { + // TODO: handle tap on comment's inline action icon (the star) + } + } + is PostNotification -> { + actionIcon.setImageResource(R.drawable.block_share) + actionIcon.isVisible = true + actionIcon.setOnClickListener { + coroutineScope.launch { + inlineActionEvents.emit( + InlineActionEvent.SharePostButtonTapped(notification) + ) + } + } + } + is Unknown -> { + actionIcon.isVisible = false + } + } + } } private val onClickListener = View.OnClickListener { view -> diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderActivityLauncher.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderActivityLauncher.java index 2aea5b62e6e1..32b2261e2527 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderActivityLauncher.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderActivityLauncher.java @@ -13,7 +13,6 @@ import androidx.core.app.ActivityOptionsCompat; import androidx.fragment.app.Fragment; -import org.wordpress.android.R; import org.wordpress.android.analytics.AnalyticsTracker; import org.wordpress.android.models.ReaderPost; import org.wordpress.android.models.ReaderTag; @@ -403,13 +402,7 @@ public static void openPost(Context context, ReaderPost post) { public static void sharePost(Context context, ReaderPost post) throws ActivityNotFoundException { String url = (post.hasShortUrl() ? post.getShortUrl() : post.getUrl()); - - Intent intent = new Intent(Intent.ACTION_SEND); - intent.setType("text/plain"); - intent.putExtra(Intent.EXTRA_TEXT, url); - intent.putExtra(Intent.EXTRA_SUBJECT, post.getTitle()); - - context.startActivity(Intent.createChooser(intent, context.getString(R.string.share_link))); + ActivityLauncher.openShareIntent(context, url, post.getTitle()); } public static void openUrl(Context context, String url, OpenUrlType openUrlType) { diff --git a/WordPress/src/main/res/drawable/block_share.xml b/WordPress/src/main/res/drawable/block_share.xml new file mode 100644 index 000000000000..7cd1f17043f0 --- /dev/null +++ b/WordPress/src/main/res/drawable/block_share.xml @@ -0,0 +1,15 @@ + + + + diff --git a/WordPress/src/main/res/layout/notifications_list_item.xml b/WordPress/src/main/res/layout/notifications_list_item.xml index 69e97762df13..716a1fb35d00 100644 --- a/WordPress/src/main/res/layout/notifications_list_item.xml +++ b/WordPress/src/main/res/layout/notifications_list_item.xml @@ -69,6 +69,7 @@ app:layout_constraintBottom_toBottomOf="@+id/note_avatar" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@+id/note_avatar" + app:tint="?attr/wpColorOnSurfaceMedium" tools:src="@drawable/star_empty" />