2
2
3
3
package org.wordpress.android.ui.mysite
4
4
5
- import android.content.SharedPreferences
6
5
import android.net.Uri
7
- import android.util.Log
8
6
import androidx.annotation.StringRes
9
7
import androidx.lifecycle.LiveData
10
8
import androidx.lifecycle.MutableLiveData
@@ -16,7 +14,6 @@ import kotlinx.coroutines.launch
16
14
import org.greenrobot.eventbus.Subscribe
17
15
import org.greenrobot.eventbus.ThreadMode.MAIN
18
16
import org.wordpress.android.R
19
- import org.wordpress.android.analytics.AnalyticsTracker
20
17
import org.wordpress.android.analytics.AnalyticsTracker.Stat
21
18
import org.wordpress.android.fluxc.Dispatcher
22
19
import org.wordpress.android.fluxc.model.SiteModel
@@ -25,7 +22,6 @@ import org.wordpress.android.fluxc.store.PostStore.OnPostUploaded
25
22
import org.wordpress.android.fluxc.store.QuickStartStore.QuickStartTask
26
23
import org.wordpress.android.modules.BG_THREAD
27
24
import org.wordpress.android.modules.UI_THREAD
28
- import org.wordpress.android.ui.accounts.login.ApplicationPasswordLoginHelper
29
25
import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureRemovalOverlayUtil
30
26
import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureRemovalPhaseHelper
31
27
import org.wordpress.android.ui.jetpackoverlay.individualplugin.WPJetpackIndividualPluginHelper
@@ -53,13 +49,9 @@ import org.wordpress.android.util.merge
53
49
import org.wordpress.android.viewmodel.Event
54
50
import org.wordpress.android.viewmodel.ScopedViewModel
55
51
import org.wordpress.android.viewmodel.SingleLiveEvent
56
- import rs.wordpress.api.kotlin.WpLoginClient
57
52
import javax.inject.Inject
58
53
import javax.inject.Named
59
- import androidx.core.content.edit
60
- import kotlinx.coroutines.withContext
61
- import org.wordpress.android.fluxc.persistence.SiteSqlUtils
62
- import rs.wordpress.api.kotlin.ApiDiscoveryResult
54
+ import org.wordpress.android.ui.mysite.cards.applicationpassword.ApplicationPasswordViewModelSlice
63
55
64
56
@Suppress(" LargeClass" , " LongMethod" , " LongParameterList" )
65
57
class MySiteViewModel @Inject constructor(
@@ -86,16 +78,12 @@ class MySiteViewModel @Inject constructor(
86
78
private val accountDataViewModelSlice : AccountDataViewModelSlice ,
87
79
private val dashboardCardsViewModelSlice : DashboardCardsViewModelSlice ,
88
80
private val dashboardItemsViewModelSlice : DashboardItemsViewModelSlice ,
89
- private val wpLoginClient : WpLoginClient ,
90
- private val applicationPasswordLoginHelper : ApplicationPasswordLoginHelper ,
91
- private val sharedPreferences : SharedPreferences ,
92
- private val siteSqlUtils : SiteSqlUtils ,
81
+ private val applicationPasswordViewModelSlice : ApplicationPasswordViewModelSlice ,
93
82
) : ScopedViewModel(mainDispatcher) {
94
83
private val _onSnackbarMessage = MutableLiveData <Event <SnackbarMessageHolder >>()
95
84
private val _onNavigation = MutableLiveData <Event <SiteNavigationAction >>()
96
85
private val _onOpenJetpackInstallFullPluginOnboarding = SingleLiveEvent <Event <Unit >>()
97
86
private val _onShowJetpackIndividualPluginOverlay = SingleLiveEvent <Event <Unit >>()
98
- private val _onShowApplicationPasswordLoginDialog = SingleLiveEvent <Event <String >>()
99
87
100
88
/* Capture and track the site selected event so we can circumvent refreshing sources on resume
101
89
as they're already built on site select. */
@@ -118,6 +106,7 @@ class MySiteViewModel @Inject constructor(
118
106
119
107
val onNavigation = merge(
120
108
_onNavigation ,
109
+ applicationPasswordViewModelSlice.onNavigation,
121
110
siteInfoHeaderCardViewModelSlice.onNavigation,
122
111
dashboardCardsViewModelSlice.onNavigation,
123
112
dashboardItemsViewModelSlice.onNavigation
@@ -133,8 +122,6 @@ class MySiteViewModel @Inject constructor(
133
122
134
123
val onShowJetpackIndividualPluginOverlay = _onShowJetpackIndividualPluginOverlay as LiveData <Event <Unit >>
135
124
136
- val onShowApplicationPasswordLoginDialog = _onShowApplicationPasswordLoginDialog as LiveData <Event <String >>
137
-
138
125
val refresh =
139
126
merge(
140
127
dashboardCardsViewModelSlice.refresh
@@ -150,26 +137,30 @@ class MySiteViewModel @Inject constructor(
150
137
151
138
val uiModel: LiveData <State > = merge(
152
139
siteInfoHeaderCardViewModelSlice.uiModel,
140
+ applicationPasswordViewModelSlice.uiModel,
153
141
accountDataViewModelSlice.uiModel,
154
142
dashboardCardsViewModelSlice.uiModel,
155
143
dashboardItemsViewModelSlice.uiModel
156
144
) { siteInfoHeaderCard,
145
+ applicationPAsswordModel,
157
146
accountData,
158
147
dashboardCards,
159
148
siteItems ->
160
149
val nonNullSiteInfoHeaderCard =
161
150
siteInfoHeaderCard ? : return @merge buildNoSiteState(accountData?.url, accountData?.name)
151
+ val headerList = listOfNotNull(nonNullSiteInfoHeaderCard, applicationPAsswordModel)
162
152
return @merge if (! dashboardCards.isNullOrEmpty<MySiteCardAndItem >())
163
- SiteSelected (dashboardData = listOf (nonNullSiteInfoHeaderCard) + dashboardCards)
153
+ SiteSelected (dashboardData = headerList + dashboardCards)
164
154
else if (! siteItems.isNullOrEmpty<MySiteCardAndItem >())
165
- SiteSelected (dashboardData = listOf (nonNullSiteInfoHeaderCard) + siteItems)
155
+ SiteSelected (dashboardData = headerList + siteItems)
166
156
else
167
- SiteSelected (dashboardData = listOf (nonNullSiteInfoHeaderCard) )
157
+ SiteSelected (dashboardData = headerList )
168
158
}.distinctUntilChanged()
169
159
170
160
init {
171
161
dispatcher.register(this )
172
162
siteInfoHeaderCardViewModelSlice.initialize(viewModelScope)
163
+ applicationPasswordViewModelSlice.initialize(viewModelScope)
173
164
dashboardCardsViewModelSlice.initialize(viewModelScope)
174
165
dashboardItemsViewModelSlice.initialize(viewModelScope)
175
166
accountDataViewModelSlice.initialize(viewModelScope)
@@ -216,85 +207,6 @@ class MySiteViewModel @Inject constructor(
216
207
}
217
208
}
218
209
219
- fun runApplicationPasswordDiscovery () {
220
- selectedSiteRepository.updateSiteSettingsIfNecessary()
221
- val site = selectedSiteRepository.getSelectedSite() ? : return
222
-
223
- val firstTimeSiteOpen = ! sharedPreferences.getBoolean(" $SITE_ALREADY_OPENED_PREFIX${site.url} " , false )
224
- if (firstTimeSiteOpen) {
225
- setSiteAsAlreadyOpened(site.url)
226
- return
227
- }
228
- viewModelScope.launch {
229
- // If the user has dismissed the authorization dialog, no need to show it again
230
- val hasDismissedAuthorizationDialog =
231
- sharedPreferences.getBoolean(" $DISMISSED_AUTHORIZATION_DIALOG_PREFIX${site.url} " , false )
232
-
233
- // If the site is already authorized, no need to run the discovery
234
- val storedSite = siteSqlUtils.getSiteWithLocalId(site.localId())
235
- if (storedSite != null &&
236
- ! storedSite.apiRestUsername.isNullOrEmpty() && ! storedSite.apiRestPassword.isNullOrEmpty()) {
237
- return @launch
238
- }
239
-
240
- if (! hasDismissedAuthorizationDialog) {
241
- val authorizationUrlComplete = getAuthorizationUrlComplete(site.url)
242
- if (authorizationUrlComplete.isNotEmpty()) {
243
- _onShowApplicationPasswordLoginDialog .value = Event (authorizationUrlComplete)
244
- }
245
- }
246
- }
247
- }
248
-
249
- @Suppress(" TooGenericExceptionCaught" )
250
- private suspend fun getAuthorizationUrlComplete (siteUrl : String ): String = withContext(bgDispatcher) {
251
- try {
252
- getAuthorizationUrlCompleteInternal(siteUrl)
253
- } catch (throwable: Throwable ) {
254
- handleAuthenticationDiscoveryError(siteUrl, throwable)
255
- }
256
- }
257
-
258
- private fun handleAuthenticationDiscoveryError (siteUrl : String , throwable : Throwable ): String {
259
- Log .e(" WP_RS" , " VM: Error during API discovery for $siteUrl " , throwable)
260
- AnalyticsTracker .track(Stat .BACKGROUND_REST_AUTODISCOVERY_FAILED )
261
- return " "
262
- }
263
-
264
- private suspend fun getAuthorizationUrlCompleteInternal (siteUrl : String ): String = withContext(bgDispatcher) {
265
- when (val urlDiscoveryResult = wpLoginClient.apiDiscovery(siteUrl)) {
266
- is ApiDiscoveryResult .Success -> {
267
- val authorizationUrl = urlDiscoveryResult.success.applicationPasswordsAuthenticationUrl.url()
268
- val authorizationUrlComplete =
269
- applicationPasswordLoginHelper.appendParamsToRestAuthorizationUrl(authorizationUrl)
270
- Log .d(" WP_RS" , " Found authorization for $siteUrl URL: $authorizationUrlComplete " )
271
- AnalyticsTracker .track(Stat .BACKGROUND_REST_AUTODISCOVERY_SUCCESSFUL )
272
- authorizationUrlComplete
273
- }
274
-
275
- is ApiDiscoveryResult .FailureFetchAndParseApiRoot ->
276
- handleAuthenticationDiscoveryError(siteUrl, Exception (" FailureFetchAndParseApiRoot" ))
277
-
278
- is ApiDiscoveryResult .FailureFindApiRoot ->
279
- handleAuthenticationDiscoveryError(siteUrl, Exception (" FailureFindApiRoot" ))
280
-
281
- is ApiDiscoveryResult .FailureParseSiteUrl ->
282
- handleAuthenticationDiscoveryError(siteUrl, urlDiscoveryResult.error)
283
- }
284
- }
285
-
286
- private fun setSiteAsAlreadyOpened (siteUrl : String ) {
287
- viewModelScope.launch {
288
- sharedPreferences.edit { putBoolean(" $SITE_ALREADY_OPENED_PREFIX$siteUrl " , true ) }
289
- }
290
- }
291
-
292
- fun onApplicationPasswordLoginDialogDismissed (siteUrl : String ) {
293
- viewModelScope.launch {
294
- sharedPreferences.edit { putBoolean(" $DISMISSED_AUTHORIZATION_DIALOG_PREFIX$siteUrl " , true ) }
295
- }
296
- }
297
-
298
210
private fun checkAndShowJetpackFullPluginInstallOnboarding () {
299
211
selectedSiteRepository.getSelectedSite()?.let { selectedSite ->
300
212
if (getShowJetpackFullPluginInstallOnboardingUseCase.execute(selectedSite)) {
@@ -468,6 +380,7 @@ class MySiteViewModel @Inject constructor(
468
380
469
381
private fun buildDashboardOrSiteItems (site : SiteModel ) {
470
382
siteInfoHeaderCardViewModelSlice.buildCard(site)
383
+ applicationPasswordViewModelSlice.buildCard(site)
471
384
if (shouldShowDashboard(site)) {
472
385
dashboardCardsViewModelSlice.buildCards(site)
473
386
dashboardItemsViewModelSlice.clearValue()
@@ -479,6 +392,7 @@ class MySiteViewModel @Inject constructor(
479
392
480
393
private fun onSitePicked (site : SiteModel ) {
481
394
siteInfoHeaderCardViewModelSlice.buildCard(site)
395
+ applicationPasswordViewModelSlice.buildCard(site)
482
396
dashboardItemsViewModelSlice.clearValue()
483
397
dashboardCardsViewModelSlice.clearValue()
484
398
dashboardCardsViewModelSlice.resetShownTracker()
@@ -553,13 +467,10 @@ class MySiteViewModel @Inject constructor(
553
467
companion object {
554
468
const val TAG_ADD_SITE_ICON_DIALOG = " TAG_ADD_SITE_ICON_DIALOG"
555
469
const val TAG_CHANGE_SITE_ICON_DIALOG = " TAG_CHANGE_SITE_ICON_DIALOG"
556
- const val TAG_REMOVE_NEXT_STEPS_DIALOG = " TAG_REMOVE_NEXT_STEPS_DIALOG"
557
470
const val SITE_NAME_CHANGE_CALLBACK_ID = 1
558
471
const val ARG_QUICK_START_TASK = " ARG_QUICK_START_TASK"
559
472
const val HIDE_WP_ADMIN_GMT_TIME_ZONE = " GMT"
560
473
private const val DELAY_BEFORE_SHOWING_JETPACK_INDIVIDUAL_PLUGIN_OVERLAY = 500L
561
474
private const val DAY_ONE_EXTERNAL_URL = " https://dayoneapp.com/?utm_source=jetpack&utm_medium=prompts"
562
- private const val DISMISSED_AUTHORIZATION_DIALOG_PREFIX = " dismissed_authorization_dialog_"
563
- private const val SITE_ALREADY_OPENED_PREFIX = " site_already_opened_"
564
475
}
565
476
}
0 commit comments