diff --git a/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsDetailListFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsDetailListFragment.kt index 9dd04a3fbd8a..101f2be19bfb 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsDetailListFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/notifications/NotificationsDetailListFragment.kt @@ -5,8 +5,6 @@ */ package org.wordpress.android.ui.notifications -import android.annotation.SuppressLint -import android.os.AsyncTask import android.os.Bundle import android.text.TextUtils import android.view.Gravity @@ -16,7 +14,11 @@ import android.view.ViewGroup import android.widget.LinearLayout import android.widget.ListView import androidx.fragment.app.ListFragment +import androidx.lifecycle.lifecycleScope import com.airbnb.lottie.LottieAnimationView +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import org.json.JSONArray import org.json.JSONException import org.wordpress.android.R @@ -36,6 +38,8 @@ import org.wordpress.android.fluxc.tools.FormattableRangeType.SITE import org.wordpress.android.fluxc.tools.FormattableRangeType.STAT import org.wordpress.android.fluxc.tools.FormattableRangeType.USER import org.wordpress.android.models.Note +import org.wordpress.android.modules.IO_THREAD +import org.wordpress.android.modules.UI_THREAD import org.wordpress.android.ui.ScrollableViewInitializedListener import org.wordpress.android.ui.ViewPagerFragment.Companion.restoreOriginalViewId import org.wordpress.android.ui.ViewPagerFragment.Companion.setUniqueIdToView @@ -66,6 +70,7 @@ import org.wordpress.android.util.image.ImageManager import org.wordpress.android.util.image.ImageType.AVATAR_WITH_BACKGROUND import org.wordpress.android.util.image.ImageType.BLAVATAR import javax.inject.Inject +import javax.inject.Named class NotificationsDetailListFragment : ListFragment(), NotificationFragment { private var restoredListPosition = 0 @@ -86,6 +91,14 @@ class NotificationsDetailListFragment : ListFragment(), NotificationFragment { @Inject lateinit var listScenarioUtils: ListScenarioUtils + @Inject + @Named(IO_THREAD) + lateinit var ioDispatcher: CoroutineDispatcher + + @Inject + @Named(UI_THREAD) + lateinit var mainDispatcher: CoroutineDispatcher + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (requireActivity().application as WordPress).component().inject(this) @@ -188,9 +201,15 @@ class NotificationsDetailListFragment : ListFragment(), NotificationFragment { super.onSaveInstanceState(outState) } - @Suppress("DEPRECATION") private fun reloadNoteBlocks() { - LoadNoteBlocksTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR) + lifecycleScope.launch(ioDispatcher) { + notification?.let { note -> + val noteBlocks = noteBlocksLoader.loadNoteBlocks(note) + withContext(mainDispatcher) { + noteBlocksLoader.handleNoteBlocks(noteBlocks) + } + } + } } fun setFooterView(footerView: ViewGroup?) { @@ -317,10 +336,7 @@ class NotificationsDetailListFragment : ListFragment(), NotificationFragment { private data class ManageUserBlockResults(val index: Int, val noteBlock: NoteBlock, val pingbackUrl: String?) // Loop through the 'body' items in this note, and create blocks for each. - // TODO replace this inner async task with a coroutine - @Suppress("DEPRECATION") - @SuppressLint("StaticFieldLeak") - private inner class LoadNoteBlocksTask : AsyncTask?>() { + private val noteBlocksLoader = object { private var mIsBadgeView = false private fun addHeaderNoteBlock(note: Note, noteList: MutableList) { @@ -460,37 +476,31 @@ class NotificationsDetailListFragment : ListFragment(), NotificationFragment { } } - @Suppress("OVERRIDE_DEPRECATION") - override fun doInBackground(vararg params: Void): List? { - if (notification == null) { - return null - } - requestReaderContentForNote() + suspend fun loadNoteBlocks(note: Note): List { + requestReaderContentForNote(note) - requireNotNull(notification).let { note -> - val bodyArray = note.body - val noteList: MutableList = ArrayList() + val bodyArray = note.body + val noteList: MutableList = ArrayList() - // Add the note header if one was provided - if (note.header != null) { - addHeaderNoteBlock(note, noteList) - } - var pingbackUrl: String? = null - val isPingback = isPingback(note) - if (bodyArray.length() > 0) { - pingbackUrl = addNotesBlock(note, noteList, bodyArray, isPingback) - } - if (isPingback) { - // Remove this when we start receiving "Read the source post block" from the backend - val generatedBlock = buildGeneratedLinkBlock( - mOnNoteBlockTextClickListener, pingbackUrl, - activity!!.getString(R.string.comment_read_source_post) - ) - generatedBlock.setIsPingback() - noteList.add(generatedBlock) - } - return noteList + // Add the note header if one was provided + if (note.header != null) { + addHeaderNoteBlock(note, noteList) } + var pingbackUrl: String? = null + val isPingback = isPingback(note) + if (bodyArray.length() > 0) { + pingbackUrl = addNotesBlock(note, noteList, bodyArray, isPingback) + } + if (isPingback) { + // Remove this when we start receiving "Read the source post block" from the backend + val generatedBlock = buildGeneratedLinkBlock( + mOnNoteBlockTextClickListener, pingbackUrl, + activity!!.getString(R.string.comment_read_source_post) + ) + generatedBlock.setIsPingback() + noteList.add(generatedBlock) + } + return noteList } private fun isPingback(note: Note): Boolean { @@ -525,8 +535,7 @@ class NotificationsDetailListFragment : ListFragment(), NotificationFragment { ) } - @Suppress("OVERRIDE_DEPRECATION") - override fun onPostExecute(noteList: List?) { + fun handleNoteBlocks(noteList: List?) { if (!isAdded || noteList == null) { return } @@ -595,37 +604,35 @@ class NotificationsDetailListFragment : ListFragment(), NotificationFragment { } // Requests Reader content for certain notification types - private fun requestReaderContentForNote() { - if (notification == null || !isAdded) { - return + private suspend fun requestReaderContentForNote(note: Note) = withContext(ioDispatcher) { + if (!isAdded) { + return@withContext } // Request the reader post so that loading reader activities will work. - if (notification!!.isUserList && !ReaderPostTable.postExists( - notification!!.siteId.toLong(), - notification!!.postId.toLong() + if (note.isUserList && !ReaderPostTable.postExists( + note.siteId.toLong(), + note.postId.toLong() ) ) { - ReaderPostActions.requestBlogPost(notification!!.siteId.toLong(), notification!!.postId.toLong(), null) + ReaderPostActions.requestBlogPost(note.siteId.toLong(), note.postId.toLong(), null) } - requireNotNull(notification).let { note -> - // Request reader comments until we retrieve the comment for this note - val isReplyOrCommentLike = note.isCommentLikeType || note.isCommentReplyType || note.isCommentWithUserReply - val commentNotExists = !ReaderCommentTable.commentExists( + // Request reader comments until we retrieve the comment for this note + val isReplyOrCommentLike = note.isCommentLikeType || note.isCommentReplyType || note.isCommentWithUserReply + val commentNotExists = !ReaderCommentTable.commentExists( + note.siteId.toLong(), + note.postId.toLong(), + note.commentId + ) + + if (isReplyOrCommentLike && commentNotExists) { + ReaderCommentService.startServiceForComment( + activity, note.siteId.toLong(), note.postId.toLong(), note.commentId ) - - if (isReplyOrCommentLike && commentNotExists) { - ReaderCommentService.startServiceForComment( - activity, - note.siteId.toLong(), - note.postId.toLong(), - note.commentId - ) - } } }