diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/action/ListAction.kt b/fluxc/src/main/java/org/wordpress/android/fluxc/action/ListAction.kt index c666d8a7c8..4d56ba76cb 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/action/ListAction.kt +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/action/ListAction.kt @@ -5,6 +5,7 @@ import org.wordpress.android.fluxc.annotations.ActionEnum import org.wordpress.android.fluxc.annotations.action.IAction import org.wordpress.android.fluxc.model.list.ListDescriptorTypeIdentifier import org.wordpress.android.fluxc.store.ListStore.FetchedListItemsPayload +import org.wordpress.android.fluxc.store.ListStore.OnListDataFailure import org.wordpress.android.fluxc.store.ListStore.ListItemsRemovedPayload import org.wordpress.android.fluxc.store.ListStore.RemoveExpiredListsPayload @@ -20,6 +21,8 @@ enum class ListAction : IAction { LIST_DATA_INVALIDATED, @Action(payloadType = RemoveExpiredListsPayload::class) REMOVE_EXPIRED_LISTS, + @Action(payloadType = OnListDataFailure::class) + LIST_DATA_FAILURE, @Action REMOVE_ALL_LISTS } diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/model/SiteModel.java b/fluxc/src/main/java/org/wordpress/android/fluxc/model/SiteModel.java index 4ed6c7196d..9d5e0f8a21 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/model/SiteModel.java +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/model/SiteModel.java @@ -21,6 +21,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.Arrays; +import java.util.List; import static java.lang.annotation.RetentionPolicy.SOURCE; @@ -251,6 +252,9 @@ public class SiteModel extends Payload implements Identifiable private String mApplicationPasswordsAuthorizeUrl; @Column private Boolean mCanBlaze; + // Comma-separated list of active features in the site's plan + @Column + private String mPlanActiveFeatures; @Override public int getId() { @@ -1076,4 +1080,20 @@ public Boolean getCanBlaze() { public void setCanBlaze(Boolean mCanBlaze) { this.mCanBlaze = mCanBlaze; } + + public boolean isHostedAtWPCom() { + return !isJetpackInstalled(); + } + + public List getPlanActiveFeaturesList() { + return Arrays.asList(mPlanActiveFeatures.split(",")); + } + + public String getPlanActiveFeatures() { + return mPlanActiveFeatures; + } + + public void setPlanActiveFeatures(final String planActiveFeatures) { + this.mPlanActiveFeatures = planActiveFeatures; + } } diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/model/list/PagedListWrapper.kt b/fluxc/src/main/java/org/wordpress/android/fluxc/model/list/PagedListWrapper.kt index 31ae7b89b8..e4a173b461 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/model/list/PagedListWrapper.kt +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/model/list/PagedListWrapper.kt @@ -15,6 +15,7 @@ import org.greenrobot.eventbus.ThreadMode import org.wordpress.android.fluxc.Dispatcher import org.wordpress.android.fluxc.store.ListStore.ListError import org.wordpress.android.fluxc.store.ListStore.OnListChanged +import org.wordpress.android.fluxc.store.ListStore.OnListDataFailure import org.wordpress.android.fluxc.store.ListStore.OnListDataInvalidated import org.wordpress.android.fluxc.store.ListStore.OnListRequiresRefresh import org.wordpress.android.fluxc.store.ListStore.OnListStateChanged @@ -152,4 +153,10 @@ class PagedListWrapper( invalidateData() } } + + @Subscribe(threadMode = ThreadMode.BACKGROUND) + @Suppress("unused") + fun onListDataFailure(event: OnListDataFailure) { + _listError.postValue(event.error) + } } diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/ApplicationPasswordsStore.kt b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/ApplicationPasswordsStore.kt index 3fa8b1786d..6c8d75e614 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/ApplicationPasswordsStore.kt +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/ApplicationPasswordsStore.kt @@ -4,6 +4,7 @@ import android.content.Context import android.content.SharedPreferences import androidx.security.crypto.EncryptedSharedPreferences import androidx.security.crypto.MasterKeys +import okhttp3.Credentials import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.util.AppLog import org.wordpress.android.util.UrlUtils @@ -21,6 +22,16 @@ class ApplicationPasswordsStore @Inject constructor( private const val UUID_PREFERENCE_KEY_PREFIX = "app_password_uuid_" } + /* + Exposed only to pass to React Native instance so we can authenticate via application password + there. Do not use directly in WCAndroid app. + */ + fun getApplicationPasswordAuthHeader(site: SiteModel): String = + Credentials.basic( + username = encryptedPreferences.getString(site.usernamePrefKey, null).orEmpty(), + password = encryptedPreferences.getString(site.passwordPrefKey, null).orEmpty() + ) + @Inject internal lateinit var configuration: ApplicationPasswordsConfiguration private val applicationName: String diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/site/SiteRestClient.kt b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/site/SiteRestClient.kt index 1da9b3bced..0d6dbbf02e 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/site/SiteRestClient.kt +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/site/SiteRestClient.kt @@ -1139,6 +1139,7 @@ class SiteRestClient @Inject constructor( site.setIsWPCom(true) } site.origin = SiteModel.ORIGIN_WPCOM_REST + site.planActiveFeatures = (from.plan?.features?.active?.joinToString(",")).orEmpty() return site } diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/site/SiteWPComRestResponse.java b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/site/SiteWPComRestResponse.java index a058a69aa5..a9491dcb5d 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/site/SiteWPComRestResponse.java +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/site/SiteWPComRestResponse.java @@ -1,5 +1,7 @@ package org.wordpress.android.fluxc.network.rest.wpcom.site; +import androidx.annotation.Nullable; + import org.wordpress.android.fluxc.network.Response; import java.util.List; @@ -43,6 +45,11 @@ public static class Plan { public String product_id; public String product_name_short; public boolean is_free; + @Nullable public Features features; + } + + public class Features { + @Nullable public List active; } public static class Capabilities { diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/persistence/WellSqlConfig.kt b/fluxc/src/main/java/org/wordpress/android/fluxc/persistence/WellSqlConfig.kt index abe52ada89..3eeda55b6e 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/persistence/WellSqlConfig.kt +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/persistence/WellSqlConfig.kt @@ -36,7 +36,7 @@ open class WellSqlConfig : DefaultWellConfig { annotation class AddOn override fun getDbVersion(): Int { - return 189 + return 190 } override fun getDbName(): String { @@ -1951,6 +1951,9 @@ open class WellSqlConfig : DefaultWellConfig { 188 -> migrate(version) { db.execSQL("ALTER TABLE SiteModel ADD CAN_BLAZE BOOLEAN") } + 189 -> migrate(version) { + db.execSQL("ALTER TABLE SiteModel ADD PLAN_ACTIVE_FEATURES TEXT") + } } } db.setTransactionSuccessful() diff --git a/fluxc/src/main/java/org/wordpress/android/fluxc/store/ListStore.kt b/fluxc/src/main/java/org/wordpress/android/fluxc/store/ListStore.kt index bf4d3d2474..484b006244 100644 --- a/fluxc/src/main/java/org/wordpress/android/fluxc/store/ListStore.kt +++ b/fluxc/src/main/java/org/wordpress/android/fluxc/store/ListStore.kt @@ -68,6 +68,7 @@ class ListStore @Inject constructor( LIST_DATA_INVALIDATED -> handleListDataInvalidated(action.payload as ListDescriptorTypeIdentifier) REMOVE_EXPIRED_LISTS -> handleRemoveExpiredLists(action.payload as RemoveExpiredListsPayload) REMOVE_ALL_LISTS -> handleRemoveAllLists() + ListAction.LIST_DATA_FAILURE -> handleDataFailure(action.payload as OnListDataFailure) } } @@ -310,6 +311,10 @@ class ListStore @Inject constructor( listSqlUtils.deleteAllLists() } + private fun handleDataFailure(event : OnListDataFailure){ + emitChange(event) + } + /** * Deletes all the items for the given [ListDescriptor]. */ @@ -398,6 +403,8 @@ class ListStore @Inject constructor( */ class ListItemsRemovedPayload(val type: ListDescriptorTypeIdentifier, val remoteItemIds: List) + class OnListDataFailure(val type: ListDescriptorTypeIdentifier) : Store.OnChanged() + /** * This is the payload for [ListAction.FETCHED_LIST_ITEMS]. * @@ -434,6 +441,7 @@ class ListStore @Inject constructor( enum class ListErrorType { GENERIC_ERROR, - PERMISSION_ERROR + PERMISSION_ERROR, + PARSE_ERROR } } diff --git a/plugins/woocommerce/src/main/kotlin/org/wordpress/android/fluxc/store/WCOrderStore.kt b/plugins/woocommerce/src/main/kotlin/org/wordpress/android/fluxc/store/WCOrderStore.kt index 6089fcc1df..8023c626af 100644 --- a/plugins/woocommerce/src/main/kotlin/org/wordpress/android/fluxc/store/WCOrderStore.kt +++ b/plugins/woocommerce/src/main/kotlin/org/wordpress/android/fluxc/store/WCOrderStore.kt @@ -30,7 +30,9 @@ import org.wordpress.android.fluxc.persistence.entity.OrderNoteEntity import org.wordpress.android.fluxc.store.ListStore.FetchedListItemsPayload import org.wordpress.android.fluxc.store.ListStore.ListError import org.wordpress.android.fluxc.store.ListStore.ListErrorType +import org.wordpress.android.fluxc.store.ListStore.OnListDataFailure import org.wordpress.android.fluxc.store.WCOrderStore.OrderErrorType.GENERIC_ERROR +import org.wordpress.android.fluxc.store.WCOrderStore.OrderErrorType.PARSE_ERROR import org.wordpress.android.fluxc.store.WCOrderStore.UpdateOrderResult.OptimisticUpdateResult import org.wordpress.android.fluxc.store.WCOrderStore.UpdateOrderResult.RemoteUpdateResult import org.wordpress.android.fluxc.tools.CoroutineEngine @@ -832,20 +834,37 @@ class WCOrderStore @Inject constructor( payload.fetchedOrders.map { it.first }.map { it.orderId }) } + // Notify listeners that the list of orders has changed (only call this if there is no error) + val listTypeIdentifier = WCOrderListDescriptor.calculateTypeIdentifier(localSiteId = payload.site.id) + if (!payload.isError) { // Save the list of orders to the database insertOrder(*payload.fetchedOrders.toTypedArray()) - // Notify listeners that the list of orders has changed (only call this if there is no error) - val listTypeIdentifier = WCOrderListDescriptor.calculateTypeIdentifier(localSiteId = payload.site.id) mDispatcher.dispatch( ListActionBuilder.newListDataInvalidatedAction( listTypeIdentifier ) ) - } + } else { + val errorType = if(payload.error.type == PARSE_ERROR){ + ListErrorType.PARSE_ERROR + } else { + ListErrorType.GENERIC_ERROR + } + mDispatcher.dispatch( + ListActionBuilder.newListDataFailureAction( + OnListDataFailure(listTypeIdentifier).apply { + error = ListError( + errorType, + payload.error.message + ) + } + ) + ) + } emitChange(onOrdersFetchedByIds) } }