Skip to content

Commit

Permalink
Merge pull request #14982 from wordpress-mobile/issue/14945-multisite…
Browse files Browse the repository at this point in the history
…-hide-restore-option

Jetpack: Hide Restore Option for Unavailable Rewind State
  • Loading branch information
ParaskP7 authored Jul 5, 2021
2 parents 4afcc44 + 71c3a07 commit 886f6e9
Show file tree
Hide file tree
Showing 18 changed files with 335 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
import static org.wordpress.android.ui.stories.StoryComposerActivity.KEY_POST_LOCAL_ID;
import static org.wordpress.android.viewmodel.activitylog.ActivityLogDetailViewModelKt.ACTIVITY_LOG_ARE_BUTTONS_VISIBLE_KEY;
import static org.wordpress.android.viewmodel.activitylog.ActivityLogDetailViewModelKt.ACTIVITY_LOG_ID_KEY;
import static org.wordpress.android.viewmodel.activitylog.ActivityLogDetailViewModelKt.ACTIVITY_LOG_IS_RESTORE_HIDDEN_KEY;
import static org.wordpress.android.viewmodel.activitylog.ActivityLogViewModelKt.ACTIVITY_LOG_REWINDABLE_ONLY_KEY;

public class ActivityLauncher {
Expand Down Expand Up @@ -688,6 +689,7 @@ public static void viewActivityLogDetailForResult(
SiteModel site,
String activityId,
boolean isButtonVisible,
boolean isRestoreHidden,
boolean rewindableOnly
) {
Map<String, Object> properties = new HashMap<>();
Expand All @@ -705,6 +707,7 @@ public static void viewActivityLogDetailForResult(
intent.putExtra(WordPress.SITE, site);
intent.putExtra(ACTIVITY_LOG_ID_KEY, activityId);
intent.putExtra(ACTIVITY_LOG_ARE_BUTTONS_VISIBLE_KEY, isButtonVisible);
intent.putExtra(ACTIVITY_LOG_IS_RESTORE_HIDDEN_KEY, isRestoreHidden);
intent.putExtra(SOURCE_TRACK_EVENT_PROPERTY_KEY, source);
activity.startActivityForResult(intent, RequestCodes.ACTIVITY_LOG_DETAIL);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package org.wordpress.android.ui.activitylog.detail

import android.content.Intent
import android.os.Bundle
import android.text.SpannableString
import android.text.method.LinkMovementMethod
import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
Expand All @@ -14,6 +16,7 @@ import org.wordpress.android.ui.ActivityLauncher
import org.wordpress.android.ui.ActivityLauncher.SOURCE_TRACK_EVENT_PROPERTY_KEY
import org.wordpress.android.ui.RequestCodes
import org.wordpress.android.ui.activitylog.detail.ActivityLogDetailNavigationEvents.ShowBackupDownload
import org.wordpress.android.ui.activitylog.detail.ActivityLogDetailNavigationEvents.ShowDocumentationPage
import org.wordpress.android.ui.activitylog.detail.ActivityLogDetailNavigationEvents.ShowRestore
import org.wordpress.android.ui.notifications.blocks.NoteBlockClickableSpan
import org.wordpress.android.ui.notifications.utils.FormattableContentClickHandler
Expand All @@ -24,6 +27,7 @@ import org.wordpress.android.util.image.ImageManager
import org.wordpress.android.util.image.ImageType.AVATAR_WITH_BACKGROUND
import org.wordpress.android.viewmodel.activitylog.ACTIVITY_LOG_ARE_BUTTONS_VISIBLE_KEY
import org.wordpress.android.viewmodel.activitylog.ACTIVITY_LOG_ID_KEY
import org.wordpress.android.viewmodel.activitylog.ACTIVITY_LOG_IS_RESTORE_HIDDEN_KEY
import org.wordpress.android.viewmodel.activitylog.ActivityLogDetailViewModel
import org.wordpress.android.viewmodel.observeEvent
import javax.inject.Inject
Expand Down Expand Up @@ -59,6 +63,7 @@ class ActivityLogDetailFragment : Fragment(R.layout.activity_log_item_detail) {
with(ActivityLogItemDetailBinding.bind(view)) {
val (site, activityLogId) = sideAndActivityId(savedInstanceState, activity.intent)
val areButtonsVisible = areButtonsVisible(savedInstanceState, activity.intent)
val isRestoreHidden = isRestoreHidden(savedInstanceState, activity.intent)

viewModel.activityLogItem.observe(viewLifecycleOwner, { activityLogModel ->
loadLogItem(activityLogModel, activity)
Expand All @@ -70,23 +75,27 @@ class ActivityLogDetailFragment : Fragment(R.layout.activity_log_item_detail) {
viewModel.downloadBackupVisible.observe(viewLifecycleOwner, { available ->
activityDownloadBackupButton.visibility = if (available == true) View.VISIBLE else View.GONE
})
viewModel.multisiteVisible.observe(viewLifecycleOwner, { available ->
checkAndShowMultisiteMessage(available)
})

viewModel.navigationEvents.observeEvent(viewLifecycleOwner, {
when (it) {
is ShowBackupDownload -> ActivityLauncher.showBackupDownloadForResult(
requireActivity(),
viewModel.site,
it.model.activityID,
RequestCodes.BACKUP_DOWNLOAD,
buildTrackingSource()
)
is ShowRestore -> ActivityLauncher.showRestoreForResult(
requireActivity(),
viewModel.site,
it.model.activityID,
RequestCodes.RESTORE,
buildTrackingSource()
)
viewModel.navigationEvents.observeEvent(viewLifecycleOwner, {
when (it) {
is ShowBackupDownload -> ActivityLauncher.showBackupDownloadForResult(
requireActivity(),
viewModel.site,
it.model.activityID,
RequestCodes.BACKUP_DOWNLOAD,
buildTrackingSource()
)
is ShowRestore -> ActivityLauncher.showRestoreForResult(
requireActivity(),
viewModel.site,
it.model.activityID,
RequestCodes.RESTORE,
buildTrackingSource()
)
is ShowDocumentationPage -> ActivityLauncher.openUrlExternal(requireContext(), it.url)
}
})

Expand All @@ -100,8 +109,22 @@ class ActivityLogDetailFragment : Fragment(R.layout.activity_log_item_detail) {
}
})

viewModel.start(site, activityLogId, areButtonsVisible)
viewModel.start(site, activityLogId, areButtonsVisible, isRestoreHidden)
}
}
}

private fun ActivityLogItemDetailBinding.checkAndShowMultisiteMessage(available: Pair<Boolean, SpannableString?>) {
if (available.first) {
with(multisiteMessage) {
linksClickable = true
isClickable = true
movementMethod = LinkMovementMethod.getInstance()
text = available.second
visibility = View.VISIBLE
}
} else {
multisiteMessage.visibility = View.GONE
}
}

Expand Down Expand Up @@ -176,11 +199,20 @@ class ActivityLogDetailFragment : Fragment(R.layout.activity_log_item_detail) {
else -> throw Throwable("Couldn't initialize Activity Log view model")
}

private fun isRestoreHidden(savedInstanceState: Bundle?, intent: Intent?) = when {
savedInstanceState != null ->
requireNotNull(savedInstanceState.getBoolean(ACTIVITY_LOG_IS_RESTORE_HIDDEN_KEY, false))
intent != null ->
intent.getBooleanExtra(ACTIVITY_LOG_IS_RESTORE_HIDDEN_KEY, false)
else -> throw Throwable("Couldn't initialize Activity Log view model")
}

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putSerializable(WordPress.SITE, viewModel.site)
outState.putString(ACTIVITY_LOG_ID_KEY, viewModel.activityLogId)
outState.putBoolean(ACTIVITY_LOG_ARE_BUTTONS_VISIBLE_KEY, viewModel.areButtonsVisible)
outState.putBoolean(ACTIVITY_LOG_IS_RESTORE_HIDDEN_KEY, viewModel.isRestoreHidden)
}

private fun ActivityLogItemDetailBinding.setActorIcon(actorIcon: String?, showJetpackIcon: Boolean?) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package org.wordpress.android.ui.activitylog.detail

const val DOCUMENTATION_PAGE_URL = "https://jetpack.com/support/backup/"

sealed class ActivityLogDetailNavigationEvents {
data class ShowBackupDownload(val model: ActivityLogDetailModel) : ActivityLogDetailNavigationEvents()
data class ShowRestore(val model: ActivityLogDetailModel) : ActivityLogDetailNavigationEvents()
data class ShowDocumentationPage(val url: String = DOCUMENTATION_PAGE_URL) : ActivityLogDetailNavigationEvents()
}
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class ActivityLogListFragment : Fragment(R.layout.activity_log_list_fragment) {
viewModel.site,
it.activityId,
it.isButtonVisible,
it.isRestoreHidden,
viewModel.rewindableOnly
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,17 @@ sealed class ActivityLogListItem(val type: ViewType) {
val rewindId: String?,
val date: Date,
override val isButtonVisible: Boolean,
val buttonIcon: Icon
val buttonIcon: Icon,
val isRestoreHidden: Boolean
) : ActivityLogListItem(EVENT), IActionableItem {
val formattedDate: String = date.toFormattedDateString()
val icon = Icon.fromValue(gridIcon)
val status = Status.fromValue(eventStatus)

constructor(
model: ActivityLogModel,
rewindDisabled: Boolean = false
rewindDisabled: Boolean,
isRestoreHidden: Boolean
) : this(
activityId = model.activityID,
title = model.summary,
Expand All @@ -49,7 +51,8 @@ sealed class ActivityLogListItem(val type: ViewType) {
rewindId = model.rewindID,
date = model.published,
isButtonVisible = !rewindDisabled && model.rewindable ?: false,
buttonIcon = MORE
buttonIcon = MORE,
isRestoreHidden = isRestoreHidden
)

override fun longId(): Long = activityId.hashCode().toLong()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,18 @@ import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import org.wordpress.android.R
import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.SecondaryAction
import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.SecondaryAction.DOWNLOAD_BACKUP
import org.wordpress.android.ui.activitylog.list.ActivityLogListItem.SecondaryAction.RESTORE
import org.wordpress.android.util.ColorUtils.setImageResourceWithTint
import org.wordpress.android.util.getColorResIdFromAttribute

class ActivityLogListItemMenuAdapter(
context: Context
context: Context,
isRestoreHidden: Boolean
) : BaseAdapter() {
private val inflater: LayoutInflater = LayoutInflater.from(context)
private val items: List<SecondaryAction> = SecondaryAction.values().toList()
private val items: List<SecondaryAction> = SecondaryAction.values()
.toList()
.filter { !(it == SecondaryAction.RESTORE && isRestoreHidden) }

override fun getCount(): Int {
return items.size
}
Expand Down Expand Up @@ -48,11 +50,11 @@ class ActivityLogListItemMenuAdapter(
val iconRes: Int
val colorRes = view.context.getColorResIdFromAttribute(R.attr.wpColorOnSurfaceMedium)
when (items[position]) {
RESTORE -> {
SecondaryAction.RESTORE -> {
textRes = R.string.activity_log_item_menu_restore_label
iconRes = R.drawable.ic_history_white_24dp
}
DOWNLOAD_BACKUP -> {
SecondaryAction.DOWNLOAD_BACKUP -> {
textRes = R.string.activity_log_item_menu_download_backup_label
iconRes = R.drawable.ic_get_app_white_24dp
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,13 @@ class EventItemViewHolder(
actionButton.setOnClickListener { renderMoreMenu(activity, it) }
}

private fun renderMoreMenu(event: ActivityLogListItem, v: View) {
private fun renderMoreMenu(
event: Event,
v: View
) {
val popup = ListPopupWindow(v.context)
popup.width = v.context.resources.getDimensionPixelSize(R.dimen.menu_item_width)
popup.setAdapter(ActivityLogListItemMenuAdapter(v.context))
popup.setAdapter(ActivityLogListItemMenuAdapter(v.context, event.isRestoreHidden))
popup.setDropDownGravity(Gravity.END)
popup.anchorView = v
popup.isModal = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ sealed class RestoreRequestState {
val published: Date? = null
) : RestoreRequestState()

object Multisite : RestoreRequestState()

object Empty : RestoreRequestState()

data class AwaitingCredentials(val isAwaitingCredentials: Boolean) : RestoreRequestState()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.model.activity.RewindStatusModel
import org.wordpress.android.fluxc.model.activity.RewindStatusModel.Reason.MULTISITE_NOT_SUPPORTED
import org.wordpress.android.fluxc.model.activity.RewindStatusModel.Rewind
import org.wordpress.android.fluxc.model.activity.RewindStatusModel.Rewind.Status.FAILED
import org.wordpress.android.fluxc.model.activity.RewindStatusModel.Rewind.Status.FINISHED
Expand All @@ -17,12 +18,13 @@ import org.wordpress.android.fluxc.store.ActivityLogStore
import org.wordpress.android.fluxc.store.ActivityLogStore.FetchRewindStatePayload
import org.wordpress.android.modules.BG_THREAD
import org.wordpress.android.ui.jetpack.restore.RestoreRequestState
import org.wordpress.android.ui.jetpack.restore.RestoreRequestState.AwaitingCredentials
import org.wordpress.android.ui.jetpack.restore.RestoreRequestState.Complete
import org.wordpress.android.ui.jetpack.restore.RestoreRequestState.Empty
import org.wordpress.android.ui.jetpack.restore.RestoreRequestState.Failure
import org.wordpress.android.ui.jetpack.restore.RestoreRequestState.AwaitingCredentials
import org.wordpress.android.ui.jetpack.restore.RestoreRequestState.Failure.NetworkUnavailable
import org.wordpress.android.ui.jetpack.restore.RestoreRequestState.Failure.RemoteRequestFailure
import org.wordpress.android.ui.jetpack.restore.RestoreRequestState.Multisite
import org.wordpress.android.ui.jetpack.restore.RestoreRequestState.Progress
import org.wordpress.android.util.AppLog
import org.wordpress.android.util.AppLog.T
Expand Down Expand Up @@ -73,7 +75,11 @@ class GetRestoreStatusUseCase @Inject constructor(
break
}
if (rewind == null) {
emit(Empty)
if (rewindStatus?.reason == MULTISITE_NOT_SUPPORTED) {
emit(Multisite)
} else {
emit(Empty)
}
break
}
if (restoreId == null || rewind.restoreId == restoreId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,34 +1,45 @@
package org.wordpress.android.viewmodel.activitylog

import android.text.SpannableString
import android.text.Spanned
import android.text.style.ClickableSpan
import android.view.View
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import org.wordpress.android.R
import org.wordpress.android.fluxc.Dispatcher
import org.wordpress.android.fluxc.model.SiteModel
import org.wordpress.android.fluxc.model.activity.ActivityLogModel.ActivityActor
import org.wordpress.android.fluxc.store.ActivityLogStore
import org.wordpress.android.fluxc.tools.FormattableRange
import org.wordpress.android.ui.activitylog.detail.ActivityLogDetailModel
import org.wordpress.android.ui.activitylog.detail.ActivityLogDetailNavigationEvents
import org.wordpress.android.ui.activitylog.detail.ActivityLogDetailNavigationEvents.ShowDocumentationPage
import org.wordpress.android.ui.utils.HtmlMessageUtils
import org.wordpress.android.util.AppLog
import org.wordpress.android.util.AppLog.T.ACTIVITY_LOG
import org.wordpress.android.util.toFormattedDateString
import org.wordpress.android.util.toFormattedTimeString
import org.wordpress.android.viewmodel.Event
import org.wordpress.android.viewmodel.ResourceProvider
import org.wordpress.android.viewmodel.SingleLiveEvent
import javax.inject.Inject

const val ACTIVITY_LOG_ID_KEY: String = "activity_log_id_key"
const val ACTIVITY_LOG_ARE_BUTTONS_VISIBLE_KEY: String = "activity_log_are_buttons_visible_key"
const val ACTIVITY_LOG_IS_RESTORE_HIDDEN_KEY: String = "activity_log_is_restore_hidden_key"

class ActivityLogDetailViewModel
@Inject constructor(
class ActivityLogDetailViewModel @Inject constructor(
val dispatcher: Dispatcher,
private val activityLogStore: ActivityLogStore
private val activityLogStore: ActivityLogStore,
private val resourceProvider: ResourceProvider,
private val htmlMessageUtils: HtmlMessageUtils
) : ViewModel() {
lateinit var site: SiteModel
lateinit var activityLogId: String
var areButtonsVisible = false
var isRestoreHidden = false

private val _navigationEvents = MutableLiveData<Event<ActivityLogDetailNavigationEvents>>()
val navigationEvents: LiveData<Event<ActivityLogDetailNavigationEvents>>
Expand All @@ -50,13 +61,24 @@ class ActivityLogDetailViewModel
val downloadBackupVisible: LiveData<Boolean>
get() = _downloadBackupVisible

fun start(site: SiteModel, activityLogId: String, areButtonsVisible: Boolean) {
private val _multisiteVisible = MutableLiveData<Pair<Boolean, SpannableString?>>()
val multisiteVisible: LiveData<Pair<Boolean, SpannableString?>>
get() = _multisiteVisible

fun start(
site: SiteModel,
activityLogId: String,
areButtonsVisible: Boolean,
isRestoreHidden: Boolean
) {
this.site = site
this.activityLogId = activityLogId
this.areButtonsVisible = areButtonsVisible
this.isRestoreHidden = isRestoreHidden

_restoreVisible.value = areButtonsVisible
_restoreVisible.value = areButtonsVisible && !isRestoreHidden
_downloadBackupVisible.value = areButtonsVisible
_multisiteVisible.value = if (isRestoreHidden) Pair(true, getMultisiteMessage()) else Pair(false, null)

if (activityLogId != _item.value?.activityID) {
_item.value = activityLogStore
Expand All @@ -80,6 +102,31 @@ class ActivityLogDetailViewModel
}
}

private fun getMultisiteMessage(): SpannableString {
val clickableText = resourceProvider.getString(R.string.activity_log_visit_our_documentation_page)
val multisiteMessage = htmlMessageUtils.getHtmlMessageFromStringFormatResId(
R.string.activity_log_multisite_message,
clickableText
)
return constructMultisiteSpan(multisiteMessage, clickableText)
}

private fun constructMultisiteSpan(
multisiteMessage: CharSequence,
clickableText: String
): SpannableString {
val clickableSpan = object : ClickableSpan() {
override fun onClick(widget: View) {
_navigationEvents.postValue(Event(ShowDocumentationPage()))
}
}
val clickableStartIndex = multisiteMessage.indexOf(clickableText)
val clickableEndIndex = clickableStartIndex + clickableText.length
val multisiteSpan = SpannableString(multisiteMessage)
multisiteSpan.setSpan(clickableSpan, clickableStartIndex, clickableEndIndex, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
return multisiteSpan
}

fun onRangeClicked(range: FormattableRange) {
_handleFormattableRangeClick.value = range
}
Expand Down
Loading

0 comments on commit 886f6e9

Please sign in to comment.