diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 4cf4532e0989..1b72edaa59ee 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -3,7 +3,8 @@ 24.0 ----- * [*] Filter media types when sharing files to the editor [https://github.com/wordpress-mobile/WordPress-Android/pull/19754] -* [**] The block editor now automatically retries failed media uploads when network connectivity is re-established. [https://github.com/wordpress-mobile/WordPress-Android/pull/19803] +* [***] [Jetpack-only] Plans: Upgrade to a Plan from domains dashboard in Jetpack app [https://github.com/wordpress-mobile/WordPress-Android/pull/19818] +* [**] [internal] Removes unused resources and code [https://github.com/wordpress-mobile/WordPress-Android/pull/19788] 23.9 ----- diff --git a/WordPress/src/androidTest/java/org/wordpress/android/ui/screenshots/WPScreenshotTest.java b/WordPress/src/androidTest/java/org/wordpress/android/ui/screenshots/WPScreenshotTest.java index 0d767d678586..1949666036c4 100644 --- a/WordPress/src/androidTest/java/org/wordpress/android/ui/screenshots/WPScreenshotTest.java +++ b/WordPress/src/androidTest/java/org/wordpress/android/ui/screenshots/WPScreenshotTest.java @@ -200,10 +200,6 @@ private void navigateMySite() { waitForElementToBeDisplayedWithoutFailure(R.id.recycler_view); - if (isElementDisplayed(R.id.tooltip_message)) { - clickOn(R.id.tooltip_message); - } - takeScreenshot("4-keep-tabs-on-your-site"); } diff --git a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt index e08ce711affc..525f505b4113 100644 --- a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt +++ b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt @@ -6,8 +6,9 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.ViewGroup import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect @@ -23,11 +24,11 @@ import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.fragment.app.Fragment -import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.fragment.app.viewModels import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.isActive import org.wordpress.android.R -import org.wordpress.android.ui.accounts.login.components.JetpackLogo +import org.wordpress.android.ui.accounts.login.components.WordpressJetpackLogo import org.wordpress.android.ui.accounts.login.components.LoopingTextWithBackground import org.wordpress.android.ui.accounts.login.components.PrimaryButton import org.wordpress.android.ui.accounts.login.components.SecondaryButton @@ -42,6 +43,7 @@ val LocalPosition = compositionLocalOf { 0f } @AndroidEntryPoint class LoginPrologueRevampedFragment : Fragment() { private lateinit var loginPrologueListener: LoginPrologueListener + private val viewModel by viewModels() override fun onCreateView( inflater: LayoutInflater, @@ -50,10 +52,16 @@ class LoginPrologueRevampedFragment : Fragment() { ) = ComposeView(requireContext()).apply { setContent { AppTheme { - PositionProvider { + PositionProvider(viewModel) { LoginScreenRevamped( - onWpComLoginClicked = loginPrologueListener::showEmailLoginScreen, - onSiteAddressLoginClicked = loginPrologueListener::loginViaSiteAddress, + onWpComLoginClicked = { + viewModel.onWpComLoginClicked() + loginPrologueListener.showEmailLoginScreen() + }, + onSiteAddressLoginClicked = { + viewModel.onSiteAddressLoginClicked() + loginPrologueListener.loginViaSiteAddress() + }, ) } } @@ -88,7 +96,7 @@ class LoginPrologueRevampedFragment : Fragment() { */ @Composable private fun PositionProvider( - viewModel: LoginPrologueRevampedViewModel = viewModel(), + viewModel: LoginPrologueRevampedViewModel, content: @Composable () -> Unit ) { val position = viewModel.positionData.observeAsState(0f) @@ -118,10 +126,10 @@ private fun LoginScreenRevamped( Box { LoopingTextWithBackground() TopLinearGradient() - JetpackLogo( + WordpressJetpackLogo( modifier = Modifier - .padding(top = 60.dp) - .size(60.dp) + .padding(top = 135.dp) + .width(132.dp) .align(Alignment.TopCenter) ) ColumnWithFrostedGlassBackground( @@ -141,6 +149,7 @@ private fun LoginScreenRevamped( @Preview(showBackground = true, device = Devices.PIXEL_4_XL) @Preview(showBackground = true, device = Devices.PIXEL_4_XL, uiMode = UI_MODE_NIGHT_YES) +@Preview(showBackground = true, device = Devices.TABLET) @Composable fun PreviewLoginScreenRevamped() { AppTheme { diff --git a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedViewModel.kt b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedViewModel.kt index c57e1b188b07..82ce069e4ab7 100644 --- a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedViewModel.kt +++ b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedViewModel.kt @@ -10,6 +10,12 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext +import org.wordpress.android.analytics.AnalyticsTracker.Stat.LOGIN_PROLOGUE_VIEWED +import org.wordpress.android.ui.accounts.UnifiedLoginTracker +import org.wordpress.android.ui.accounts.UnifiedLoginTracker.Click +import org.wordpress.android.ui.accounts.UnifiedLoginTracker.Flow +import org.wordpress.android.ui.accounts.UnifiedLoginTracker.Step +import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper import javax.inject.Inject import kotlin.math.PI @@ -33,6 +39,8 @@ private const val DEFAULT_PITCH = (-30 * PI / 180).toFloat() @HiltViewModel class LoginPrologueRevampedViewModel @Inject constructor( + private val unifiedLoginTracker: UnifiedLoginTracker, + analyticsTrackerWrapper: AnalyticsTrackerWrapper, @ApplicationContext appContext: Context, ) : ViewModel() { private val accelerometerData = FloatArray(3) @@ -41,6 +49,11 @@ class LoginPrologueRevampedViewModel @Inject constructor( private val orientationAngles = floatArrayOf(0f, DEFAULT_PITCH, 0f) private var position = 0f + init { + analyticsTrackerWrapper.track(stat = LOGIN_PROLOGUE_VIEWED) + unifiedLoginTracker.track(flow = Flow.PROLOGUE, step = Step.PROLOGUE) + } + /** * This function updates the physics model for the interactive animation by applying the elapsed time (in seconds) * to update the velocity and position. @@ -62,6 +75,14 @@ class LoginPrologueRevampedViewModel @Inject constructor( } } + fun onWpComLoginClicked() { + unifiedLoginTracker.trackClick(Click.CONTINUE_WITH_WORDPRESS_COM) + } + + fun onSiteAddressLoginClicked() { + unifiedLoginTracker.trackClick(Click.LOGIN_WITH_SITE_ADDRESS) + } + /** * This LiveData responds to orientation data to calculate the pitch of the device. This is then used to update the * velocity and position for each frame. diff --git a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/PrimaryButton.kt b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/PrimaryButton.kt index 99ff924ea0ae..d9cd6bd25b9e 100644 --- a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/PrimaryButton.kt +++ b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/PrimaryButton.kt @@ -13,6 +13,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import org.wordpress.android.R import org.wordpress.android.ui.compose.unit.Margin @@ -38,9 +39,8 @@ fun PrimaryButton( ) { Text( text = stringResource(R.string.continue_with_wpcom_no_signup), - style = TextStyle( - fontWeight = FontWeight.SemiBold, - ), + style = TextStyle(fontWeight = FontWeight.Medium, fontSize = 16.sp), + modifier = Modifier.padding(vertical = 8.dp), ) } } diff --git a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/SecondaryButton.kt b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/SecondaryButton.kt index d45f56d38773..a4a776781188 100644 --- a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/SecondaryButton.kt +++ b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/SecondaryButton.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import org.wordpress.android.R @Composable @@ -38,9 +39,8 @@ fun SecondaryButton( ) { Text( text = stringResource(R.string.enter_your_site_address), - style = TextStyle( - fontWeight = FontWeight.Medium, - ), + style = TextStyle(fontWeight = FontWeight.Normal, fontSize = 16.sp), + modifier = Modifier.padding(vertical = 8.dp), ) } } diff --git a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/TopLinearGradient.kt b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/TopLinearGradient.kt index 675407fe8eef..0eb3f569b916 100644 --- a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/TopLinearGradient.kt +++ b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/TopLinearGradient.kt @@ -21,7 +21,7 @@ fun TopLinearGradient(modifier: Modifier = Modifier) { contentScale = ContentScale.FillBounds, modifier = modifier .fillMaxWidth() - .fillMaxHeight(0.62f) + .fillMaxHeight(0.82f) ) } diff --git a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/JetpackLogo.kt b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/WordpressJetpackLogo.kt similarity index 78% rename from WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/JetpackLogo.kt rename to WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/WordpressJetpackLogo.kt index 9d3c0a4b15de..97a599c6a3d3 100644 --- a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/JetpackLogo.kt +++ b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/WordpressJetpackLogo.kt @@ -8,9 +8,9 @@ import androidx.compose.ui.res.stringResource import org.wordpress.android.R @Composable -fun JetpackLogo(modifier: Modifier = Modifier) { +fun WordpressJetpackLogo(modifier: Modifier = Modifier) { Image( - painter = painterResource(R.drawable.ic_jetpack_logo_green_24dp), + painter = painterResource(R.drawable.ic_wordpress_jetpack_welcome), contentDescription = stringResource( R.string.login_prologue_revamped_content_description_jetpack_logo ), diff --git a/WordPress/src/jetpack/res/drawable-hdpi/bg_jetpack_login_splash.png b/WordPress/src/jetpack/res/drawable-hdpi/bg_jetpack_login_splash.png deleted file mode 100644 index 299cdc03c09c..000000000000 Binary files a/WordPress/src/jetpack/res/drawable-hdpi/bg_jetpack_login_splash.png and /dev/null differ diff --git a/WordPress/src/jetpack/res/drawable-hdpi/bg_jetpack_login_splash.webp b/WordPress/src/jetpack/res/drawable-hdpi/bg_jetpack_login_splash.webp new file mode 100644 index 000000000000..b8950bcab6bf Binary files /dev/null and b/WordPress/src/jetpack/res/drawable-hdpi/bg_jetpack_login_splash.webp differ diff --git a/WordPress/src/jetpack/res/drawable-mdpi/bg_jetpack_login_splash.png b/WordPress/src/jetpack/res/drawable-mdpi/bg_jetpack_login_splash.png deleted file mode 100644 index 2b7af6636c1a..000000000000 Binary files a/WordPress/src/jetpack/res/drawable-mdpi/bg_jetpack_login_splash.png and /dev/null differ diff --git a/WordPress/src/jetpack/res/drawable-mdpi/bg_jetpack_login_splash.webp b/WordPress/src/jetpack/res/drawable-mdpi/bg_jetpack_login_splash.webp new file mode 100644 index 000000000000..94c70cc537b0 Binary files /dev/null and b/WordPress/src/jetpack/res/drawable-mdpi/bg_jetpack_login_splash.webp differ diff --git a/WordPress/src/jetpack/res/drawable-night-hdpi/bg_jetpack_login_splash.webp b/WordPress/src/jetpack/res/drawable-night-hdpi/bg_jetpack_login_splash.webp new file mode 100644 index 000000000000..9dc130a0c6ac Binary files /dev/null and b/WordPress/src/jetpack/res/drawable-night-hdpi/bg_jetpack_login_splash.webp differ diff --git a/WordPress/src/jetpack/res/drawable-night-mdpi/bg_jetpack_login_splash.webp b/WordPress/src/jetpack/res/drawable-night-mdpi/bg_jetpack_login_splash.webp new file mode 100644 index 000000000000..d9ec24404ef2 Binary files /dev/null and b/WordPress/src/jetpack/res/drawable-night-mdpi/bg_jetpack_login_splash.webp differ diff --git a/WordPress/src/jetpack/res/drawable-night-xhdpi/bg_jetpack_login_splash.webp b/WordPress/src/jetpack/res/drawable-night-xhdpi/bg_jetpack_login_splash.webp new file mode 100644 index 000000000000..250e9a44d281 Binary files /dev/null and b/WordPress/src/jetpack/res/drawable-night-xhdpi/bg_jetpack_login_splash.webp differ diff --git a/WordPress/src/jetpack/res/drawable-night-xxhdpi/bg_jetpack_login_splash.webp b/WordPress/src/jetpack/res/drawable-night-xxhdpi/bg_jetpack_login_splash.webp new file mode 100644 index 000000000000..8c5d32b2d5f1 Binary files /dev/null and b/WordPress/src/jetpack/res/drawable-night-xxhdpi/bg_jetpack_login_splash.webp differ diff --git a/WordPress/src/jetpack/res/drawable-night-xxxhdpi/bg_jetpack_login_splash.webp b/WordPress/src/jetpack/res/drawable-night-xxxhdpi/bg_jetpack_login_splash.webp new file mode 100644 index 000000000000..3ffccfc59c2c Binary files /dev/null and b/WordPress/src/jetpack/res/drawable-night-xxxhdpi/bg_jetpack_login_splash.webp differ diff --git a/WordPress/src/jetpack/res/drawable-xhdpi/bg_jetpack_login_splash.png b/WordPress/src/jetpack/res/drawable-xhdpi/bg_jetpack_login_splash.png deleted file mode 100644 index b61298a20e30..000000000000 Binary files a/WordPress/src/jetpack/res/drawable-xhdpi/bg_jetpack_login_splash.png and /dev/null differ diff --git a/WordPress/src/jetpack/res/drawable-xhdpi/bg_jetpack_login_splash.webp b/WordPress/src/jetpack/res/drawable-xhdpi/bg_jetpack_login_splash.webp new file mode 100644 index 000000000000..8a1f06d99be5 Binary files /dev/null and b/WordPress/src/jetpack/res/drawable-xhdpi/bg_jetpack_login_splash.webp differ diff --git a/WordPress/src/jetpack/res/drawable-xxhdpi/bg_jetpack_login_splash.png b/WordPress/src/jetpack/res/drawable-xxhdpi/bg_jetpack_login_splash.png deleted file mode 100644 index a5f93290e88e..000000000000 Binary files a/WordPress/src/jetpack/res/drawable-xxhdpi/bg_jetpack_login_splash.png and /dev/null differ diff --git a/WordPress/src/jetpack/res/drawable-xxhdpi/bg_jetpack_login_splash.webp b/WordPress/src/jetpack/res/drawable-xxhdpi/bg_jetpack_login_splash.webp new file mode 100644 index 000000000000..30fb1d6f79e0 Binary files /dev/null and b/WordPress/src/jetpack/res/drawable-xxhdpi/bg_jetpack_login_splash.webp differ diff --git a/WordPress/src/jetpack/res/drawable-xxxhdpi/bg_jetpack_login_splash.png b/WordPress/src/jetpack/res/drawable-xxxhdpi/bg_jetpack_login_splash.png deleted file mode 100644 index 6d067583cb3d..000000000000 Binary files a/WordPress/src/jetpack/res/drawable-xxxhdpi/bg_jetpack_login_splash.png and /dev/null differ diff --git a/WordPress/src/jetpack/res/drawable-xxxhdpi/bg_jetpack_login_splash.webp b/WordPress/src/jetpack/res/drawable-xxxhdpi/bg_jetpack_login_splash.webp new file mode 100644 index 000000000000..a748e8c295a0 Binary files /dev/null and b/WordPress/src/jetpack/res/drawable-xxxhdpi/bg_jetpack_login_splash.webp differ diff --git a/WordPress/src/jetpack/res/drawable/ic_wordpress_jetpack_welcome.xml b/WordPress/src/jetpack/res/drawable/ic_wordpress_jetpack_welcome.xml new file mode 100644 index 000000000000..28203799ace5 --- /dev/null +++ b/WordPress/src/jetpack/res/drawable/ic_wordpress_jetpack_welcome.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/WordPress/src/jetpack/res/values-night/colors.xml b/WordPress/src/jetpack/res/values-night/colors.xml index 44cd0e9470c2..c69c0610ccf9 100644 --- a/WordPress/src/jetpack/res/values-night/colors.xml +++ b/WordPress/src/jetpack/res/values-night/colors.xml @@ -6,20 +6,20 @@ @color/jetpack_green_40 - @color/jetpack_green_100 + @color/wordpress_blue_100 - @color/jetpack_green_0 - @color/jetpack_green_80 + #3858E9 + @color/white @color/white - #99011D0A + #CC050A21 #08FFFFFF - #FC001C09 - #FA001C09 - #D9001C09 - #00001C09 + #050A21 + #E6050A21 + #E6050A21 + #00050A21 - @color/jetpack_green_20 - @color/jetpack_green_50 + #3858E9 + @color/jetpack_green_40 diff --git a/WordPress/src/jetpack/res/values/colors.xml b/WordPress/src/jetpack/res/values/colors.xml index 19d4fc313529..912bd27f7c05 100644 --- a/WordPress/src/jetpack/res/values/colors.xml +++ b/WordPress/src/jetpack/res/values/colors.xml @@ -8,19 +8,19 @@ @color/jetpack_green_0 - @color/jetpack_green_50 + #3858E9 @color/white - @color/jetpack_green_90 + @color/wordpress_blue_100 - #99F1F3EC + #CCF1F3EC #0D000000 - #FCF1F3EC - #FAF1F3EC - #D9F1F3EC - #00F1F3EC + #FCFFFFFF + #FAFFFFFF + #D9FFFFFF + #00FFFFFF - #80008710 - @color/jetpack_green_50 + #3858E9 + @color/jetpack_green_40 diff --git a/WordPress/src/jetpack/res/values/strings.xml b/WordPress/src/jetpack/res/values/strings.xml index 616900674fef..0d3260586334 100644 --- a/WordPress/src/jetpack/res/values/strings.xml +++ b/WordPress/src/jetpack/res/values/strings.xml @@ -21,10 +21,14 @@ Respond to comments Restore a backup Search for plugins - Share on Facebook + Share on social Fix a security issue Post a photo - Add an author + Read other blogs + Build an audience + Post a photo + Write from anywhere + Manage your domains Check your email on this device and tap the link in the email you received from Jetpack.com. diff --git a/WordPress/src/jetpack/res/values/texts_login_prologue_jetpack_features.xml b/WordPress/src/jetpack/res/values/texts_login_prologue_jetpack_features.xml index 271efb332906..dc40eb9edcce 100644 --- a/WordPress/src/jetpack/res/values/texts_login_prologue_jetpack_features.xml +++ b/WordPress/src/jetpack/res/values/texts_login_prologue_jetpack_features.xml @@ -13,5 +13,9 @@ @string/login_prologue_revamped_jetpack_feature_text_10 @string/login_prologue_revamped_jetpack_feature_text_11 @string/login_prologue_revamped_jetpack_feature_text_12 + @string/login_prologue_revamped_jetpack_feature_text_13 + @string/login_prologue_revamped_jetpack_feature_text_14 + @string/login_prologue_revamped_jetpack_feature_text_15 + @string/login_prologue_revamped_jetpack_feature_text_16 diff --git a/WordPress/src/main/AndroidManifest.xml b/WordPress/src/main/AndroidManifest.xml index d1cf90a93cfd..56d049968bb8 100644 --- a/WordPress/src/main/AndroidManifest.xml +++ b/WordPress/src/main/AndroidManifest.xml @@ -428,45 +428,45 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + diff --git a/WordPress/src/main/java/org/wordpress/android/JavaScriptException.java b/WordPress/src/main/java/org/wordpress/android/JavaScriptException.java deleted file mode 100644 index 3568159949be..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/JavaScriptException.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.wordpress.android; - -public class JavaScriptException extends Throwable { - String mFile; - int mLine; - - public JavaScriptException(String file, int line, String message) { - super(message); - mFile = file; - mLine = line; - fillInStackTrace(); - } - - @Override - public Throwable fillInStackTrace() { - setStackTrace(new StackTraceElement[]{ - new StackTraceElement("JavaScriptException", "", mFile, mLine) - }); - return this; - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ActivityNavigator.kt b/WordPress/src/main/java/org/wordpress/android/ui/ActivityNavigator.kt index 997cd17fcbfa..d3e0c0760d7e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/ActivityNavigator.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/ActivityNavigator.kt @@ -134,6 +134,23 @@ class ActivityNavigator @Inject constructor() { context.startActivity(intent) } + fun openMediaPickerInNewStack(context: Context, site: SiteModel?) { + if (site == null) { + ToastUtils.showToast(context, R.string.media_cannot_be_started, ToastUtils.Duration.SHORT) + return + } + AnalyticsUtils.trackWithSiteDetails(AnalyticsTracker.Stat.OPENED_MEDIA_LIBRARY, site) + val taskStackBuilder = TaskStackBuilder.create(context) + val mainActivityIntent = getMainActivityInNewStack(context) + val intent = Intent(context, MediaBrowserActivity::class.java) + intent.putExtra(WordPress.SITE, site) + intent.putExtra(MediaBrowserActivity.ARG_LAUNCH_PHOTO_PICKER, true) + taskStackBuilder + .addNextIntent(mainActivityIntent) + .addNextIntent(intent) + .startActivities() + } + private fun getMainActivityInNewStack(context: Context): Intent { val mainActivityIntent = Intent(context, WPMainActivity::class.java) mainActivityIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/ExpandableHeightGridView.java b/WordPress/src/main/java/org/wordpress/android/ui/ExpandableHeightGridView.java deleted file mode 100644 index f900e418a50c..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/ui/ExpandableHeightGridView.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.wordpress.android.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.ViewGroup; -import android.widget.GridView; - -// based on http://stackoverflow.com/questions/8481844/gridview-height-gets-cut - -public class ExpandableHeightGridView extends GridView { - boolean mIsExpanded = false; - - public ExpandableHeightGridView(Context context) { - super(context); - } - - public ExpandableHeightGridView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ExpandableHeightGridView(Context context, AttributeSet attrs, - int defStyle) { - super(context, attrs, defStyle); - } - - public boolean isExpanded() { - return mIsExpanded; - } - - @Override - public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (isExpanded()) { - // Calculate entire height by providing a very large height hint. - // View.MEASURED_SIZE_MASK represents the largest height possible. - int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, - MeasureSpec.AT_MOST); - super.onMeasure(widthMeasureSpec, expandSpec); - - ViewGroup.LayoutParams params = getLayoutParams(); - params.height = getMeasuredHeight(); - } else { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - } - - public void setExpanded(boolean expanded) { - this.mIsExpanded = expanded; - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/DeepLinkNavigator.kt b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/DeepLinkNavigator.kt index d21857723473..58b2598d1c40 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/DeepLinkNavigator.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/DeepLinkNavigator.kt @@ -33,7 +33,7 @@ import javax.inject.Inject class DeepLinkNavigator @Inject constructor(private val activityNavigator: ActivityNavigator) { - @Suppress("ComplexMethod") + @Suppress("ComplexMethod", "LongMethod") fun handleNavigationAction(navigateAction: NavigateAction, activity: AppCompatActivity) { when (navigateAction) { LoginForResult -> ActivityLauncher.loginForDeeplink(activity) @@ -86,6 +86,11 @@ class DeepLinkNavigator ActivityLauncher.showJetpackStaticPoster(activity) is NavigateAction.OpenMediaForSite -> activityNavigator.openMediaInNewStack(activity, navigateAction.site) NavigateAction.OpenMedia -> activityNavigator.openMediaInNewStack(activity) + is NavigateAction.OpenMediaPickerForSite -> activityNavigator.openMediaPickerInNewStack( + activity, + navigateAction.site + ) + NavigateAction.DomainManagement -> ActivityLauncher.openDomainManagement(activity) } if (navigateAction != LoginForResult) { activity.finish() @@ -119,5 +124,7 @@ class DeepLinkNavigator object OpenJetpackStaticPosterView : NavigateAction() data class OpenMediaForSite(val site: SiteModel) : NavigateAction() object OpenMedia : NavigateAction() + data class OpenMediaPickerForSite(val site: SiteModel) : NavigateAction() + object DomainManagement : NavigateAction() } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/DeepLinkTrackingUtils.kt b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/DeepLinkTrackingUtils.kt index 2b70b5970622..4c2aefe46248 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/DeepLinkTrackingUtils.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/DeepLinkTrackingUtils.kt @@ -6,7 +6,11 @@ import org.wordpress.android.ui.deeplinks.DeepLinkNavigator.NavigateAction.OpenI import org.wordpress.android.ui.deeplinks.DeepLinkTrackingUtils.DeepLinkSource.BANNER import org.wordpress.android.ui.deeplinks.DeepLinkTrackingUtils.DeepLinkSource.EMAIL import org.wordpress.android.ui.deeplinks.DeepLinkTrackingUtils.DeepLinkSource.LINK +import org.wordpress.android.ui.deeplinks.DeepLinkTrackingUtils.DeepLinkSource.QRCODE_AUTH +import org.wordpress.android.ui.deeplinks.DeepLinkTrackingUtils.DeepLinkSource.QRCODE_MEDIA import org.wordpress.android.ui.deeplinks.handlers.DeepLinkHandlers +import org.wordpress.android.ui.deeplinks.handlers.QRCodeAuthLinkHandler +import org.wordpress.android.ui.deeplinks.handlers.QRCodeMediaLinkHandler import org.wordpress.android.util.UriWrapper import org.wordpress.android.util.analytics.AnalyticsUtilsWrapper import javax.inject.Inject @@ -54,7 +58,7 @@ class DeepLinkTrackingUtils val trackingSource = source ?: if (uri.host == DeepLinkingIntentReceiverViewModel.HOST_WORDPRESS_COM) { LINK } else { - BANNER + applyBannerOrQrCodeSourceFromUri(uri) } return TrackingData(trackingSource, url ?: "", sourceInfo) } @@ -69,9 +73,22 @@ class DeepLinkTrackingUtils } ?: uri } + private fun applyBannerOrQrCodeSourceFromUri(uri: UriWrapper): DeepLinkSource { + return when (uri.getQueryParameter("campaign")) { + null -> BANNER + QRCodeMediaLinkHandler.CAMPAIGN_TYPE -> QRCODE_MEDIA + QRCodeAuthLinkHandler.CAMPAIGN_TYPE -> QRCODE_AUTH + else -> LINK + } + } + data class TrackingData(val source: DeepLinkSource, val url: String, val sourceInfo: String? = null) enum class DeepLinkSource(val value: String) { - EMAIL("email"), BANNER("banner"), LINK("link") + EMAIL("email"), + BANNER("banner"), + LINK("link"), + QRCODE_AUTH("qr-code-auth"), + QRCODE_MEDIA("qr-code-media") } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/DeepLinkingIntentReceiverActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/DeepLinkingIntentReceiverActivity.java index 387262386fea..55c85be36fe6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/DeepLinkingIntentReceiverActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/DeepLinkingIntentReceiverActivity.java @@ -1,5 +1,6 @@ package org.wordpress.android.ui.deeplinks; +import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -152,4 +153,11 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { finish(); } } + + public static void openDeepLinkUrl(@NonNull Context context, @NonNull String url) { + Intent intent = new Intent(context, DeepLinkingIntentReceiverActivity.class); + intent.setData(Uri.parse(url)); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + getContext().startActivity(intent); + } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/DeepLinkHandlers.kt b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/DeepLinkHandlers.kt index 19b49b039e09..c089152827a4 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/DeepLinkHandlers.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/DeepLinkHandlers.kt @@ -17,7 +17,9 @@ class DeepLinkHandlers notificationsLinkHandler: NotificationsLinkHandler, qrCodeAuthLinkHandler: QRCodeAuthLinkHandler, homeLinkHandler: HomeLinkHandler, - mediaLinkHandler: MediaLinkHandler + mediaLinkHandler: MediaLinkHandler, + domainManagementLinkHandler: DomainManagementLinkHandler, + qrCodeMediaLinkHandler: QRCodeMediaLinkHandler, ) { private val handlers = listOf( editorLinkHandler, @@ -28,7 +30,9 @@ class DeepLinkHandlers notificationsLinkHandler, qrCodeAuthLinkHandler, homeLinkHandler, - mediaLinkHandler + mediaLinkHandler, + domainManagementLinkHandler, + qrCodeMediaLinkHandler, ) private val _toast by lazy { @@ -50,6 +54,10 @@ class DeepLinkHandlers return handlers.firstOrNull { it.shouldHandleUrl(uri) }?.buildNavigateAction(uri) } + fun isDeepLink(url: String): Boolean { + return handlers.any { it.shouldHandleUrl(UriWrapper(url)) } + } + fun stripUrl(uri: UriWrapper): String? { return handlers.firstOrNull { it.shouldHandleUrl(uri) }?.stripUrl(uri) } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/DomainManagementLinkHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/DomainManagementLinkHandler.kt new file mode 100644 index 000000000000..e5556dadfb72 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/DomainManagementLinkHandler.kt @@ -0,0 +1,44 @@ +package org.wordpress.android.ui.deeplinks.handlers + +import org.wordpress.android.ui.deeplinks.DeepLinkNavigator.NavigateAction +import org.wordpress.android.ui.deeplinks.DeepLinkNavigator.NavigateAction.DomainManagement +import org.wordpress.android.ui.deeplinks.DeepLinkingIntentReceiverViewModel.Companion.HOST_WORDPRESS_COM +import org.wordpress.android.util.UriWrapper +import javax.inject.Inject + +class DomainManagementLinkHandler +@Inject constructor() : DeepLinkHandler { + /** + * Returns true if the URI looks like `https://wordpress.com/me/domains` or `https://wordpress.com/domains/manage` + */ + override fun shouldHandleUrl(uri: UriWrapper): Boolean { + return (uri.host == HOST_WORDPRESS_COM && + (uri.pathSegments.isMeDomainsScheme() || uri.pathSegments.isDomainsManagementScheme())) + } + + private fun List.isMeDomainsScheme() = + size == 2 && this[0] == ME_DOMAINS_SEGMENT1 && this[1] == ME_DOMAINS_SEGMENT2 + + private fun List.isDomainsManagementScheme() = + size == 2 && this[0] == DOMAINS_MANAGE_SEGMENT1 && this[1] == DOMAINS_MANAGE_SEGMENT2 + + override fun buildNavigateAction(uri: UriWrapper): NavigateAction = DomainManagement + + override fun stripUrl(uri: UriWrapper): String { + return buildString { + append("$HOST_WORDPRESS_COM/") + if (uri.pathSegments.isMeDomainsScheme()) { + append("$ME_DOMAINS_SEGMENT1/$ME_DOMAINS_SEGMENT2") + } else { + append("$DOMAINS_MANAGE_SEGMENT1/$DOMAINS_MANAGE_SEGMENT2") + } + } + } + + companion object { + private const val ME_DOMAINS_SEGMENT1 = "me" + private const val ME_DOMAINS_SEGMENT2 = "domains" + private const val DOMAINS_MANAGE_SEGMENT1 = "domains" + private const val DOMAINS_MANAGE_SEGMENT2 = "manage" + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/QRCodeAuthLinkHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/QRCodeAuthLinkHandler.kt index 07d3bca511ec..5bb2f732b74e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/QRCodeAuthLinkHandler.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/QRCodeAuthLinkHandler.kt @@ -12,7 +12,8 @@ class QRCodeAuthLinkHandler @Inject constructor() : DeepLinkHandler { override fun shouldHandleUrl(uri: UriWrapper): Boolean { // https://apps.wordpress.com/get/?campaign=login-qr-code#qr-code-login?token=XXXX&data=XXXXX return uri.host == HOST_APPS_WORDPRESS_COM && - uri.pathSegments.firstOrNull() == GET_PATH + uri.pathSegments.firstOrNull() == GET_PATH && + uri.getQueryParameter(CAMPAIGN) == CAMPAIGN_TYPE } override fun buildNavigateAction(uri: UriWrapper): NavigateAction { @@ -28,5 +29,7 @@ class QRCodeAuthLinkHandler @Inject constructor() : DeepLinkHandler { companion object { private const val GET_PATH = "get" private const val HOST_APPS_WORDPRESS_COM = "apps.wordpress.com" + private const val CAMPAIGN = "campaign" + const val CAMPAIGN_TYPE = "login-qr-code" } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/QRCodeMediaLinkHandler.kt b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/QRCodeMediaLinkHandler.kt new file mode 100644 index 000000000000..5278611ef8e6 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/deeplinks/handlers/QRCodeMediaLinkHandler.kt @@ -0,0 +1,53 @@ +package org.wordpress.android.ui.deeplinks.handlers + +import org.wordpress.android.ui.deeplinks.DeepLinkNavigator.NavigateAction +import org.wordpress.android.ui.deeplinks.DeepLinkUriUtils +import org.wordpress.android.util.UriWrapper +import javax.inject.Inject + +class QRCodeMediaLinkHandler @Inject constructor( + private val deepLinkUriUtils: DeepLinkUriUtils +) : DeepLinkHandler { + /** + * Returns true if the URI looks like `apps.wordpress.com/get` + */ + override fun shouldHandleUrl(uri: UriWrapper): Boolean { + // https://apps.wordpress.com/get/?campaign=qr-code-media&data=post_id:6,site_id:227148183 + return uri.host == HOST_APPS_WORDPRESS_COM && + uri.pathSegments.firstOrNull() == GET_PATH && + uri.getQueryParameter(CAMPAIGN) == CAMPAIGN_TYPE + } + + override fun buildNavigateAction(uri: UriWrapper): NavigateAction { + val extractedSiteId = extractSiteIdFromUrl(uri) + return when (val siteModel = extractedSiteId?.let { siteId -> deepLinkUriUtils.blogIdToSite(siteId) }) { + null -> { + NavigateAction.OpenMySite + } + else -> { + NavigateAction.OpenMediaPickerForSite(siteModel) + } + } + } + + override fun stripUrl(uri: UriWrapper): String { + return buildString { + append("$HOST_APPS_WORDPRESS_COM/$GET_PATH") + } + } + + private fun extractSiteIdFromUrl(uri: UriWrapper): String? { + uri.getQueryParameter("data")?.let { data -> + val siteIdPair = data.split(",").find { it.startsWith("site_id:") } + return siteIdPair?.substringAfter(":") + } + return null + } + + companion object { + private const val GET_PATH = "get" + private const val HOST_APPS_WORDPRESS_COM = "apps.wordpress.com" + private const val CAMPAIGN = "campaign" + const val CAMPAIGN_TYPE = "qr-code-media" + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardAdapter.kt b/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardAdapter.kt index a160888254d9..5ca9b2d869cb 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardAdapter.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardAdapter.kt @@ -10,12 +10,14 @@ import org.wordpress.android.ui.domains.DomainsDashboardItem.ManageDomains import org.wordpress.android.ui.domains.DomainsDashboardItem.PurchaseDomain import org.wordpress.android.ui.domains.DomainsDashboardItem.SiteDomains import org.wordpress.android.ui.domains.DomainsDashboardItem.SiteDomainsHeader +import org.wordpress.android.ui.domains.DomainsDashboardItem.PurchasePlan import org.wordpress.android.ui.domains.DomainsDashboardItem.Type import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.ADD_DOMAIN import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.DOMAIN_BLURB import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.MANAGE_DOMAINS import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.PRIMARY_DOMAIN import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.PURCHASE_DOMAIN +import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.PURCHASE_PLAN import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.SITE_DOMAINS import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.SITE_DOMAINS_HEADER import org.wordpress.android.ui.domains.DomainsDashboardViewHolder.AddDomainViewHolder @@ -25,6 +27,7 @@ import org.wordpress.android.ui.domains.DomainsDashboardViewHolder.ManageDomains import org.wordpress.android.ui.domains.DomainsDashboardViewHolder.PurchaseDomainViewHolder import org.wordpress.android.ui.domains.DomainsDashboardViewHolder.SiteDomainsHeaderViewHolder import org.wordpress.android.ui.domains.DomainsDashboardViewHolder.SiteDomainsViewHolder +import org.wordpress.android.ui.domains.DomainsDashboardViewHolder.PurchasePlanViewHolder import org.wordpress.android.ui.utils.UiHelpers import javax.inject.Inject @@ -40,6 +43,7 @@ class DomainsDashboardAdapter @Inject constructor( MANAGE_DOMAINS -> ManageDomainsViewHolder(parent) PURCHASE_DOMAIN -> PurchaseDomainViewHolder(parent, uiHelpers) DOMAIN_BLURB -> DomainBlurbViewHolder(parent, uiHelpers) + PURCHASE_PLAN -> PurchasePlanViewHolder(parent, uiHelpers) } } @@ -53,6 +57,7 @@ class DomainsDashboardAdapter @Inject constructor( is ManageDomainsViewHolder -> holder.onBind(item as ManageDomains) is PurchaseDomainViewHolder -> holder.onBind(item as PurchaseDomain) is DomainBlurbViewHolder -> holder.onBind(item as DomainBlurb) + is PurchasePlanViewHolder -> holder.onBind(item as PurchasePlan) } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardFragment.kt index ce46ee60a279..bb60d9f91380 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardFragment.kt @@ -21,8 +21,10 @@ import org.wordpress.android.ui.ActivityLauncher import org.wordpress.android.ui.RequestCodes.DOMAIN_REGISTRATION import org.wordpress.android.ui.domains.DomainRegistrationActivity.DomainRegistrationPurpose.CTA_DOMAIN_CREDIT_REDEMPTION import org.wordpress.android.ui.domains.DomainRegistrationActivity.DomainRegistrationPurpose.DOMAIN_PURCHASE +import org.wordpress.android.ui.domains.DomainRegistrationActivity.DomainRegistrationPurpose.FREE_DOMAIN_WITH_ANNUAL_PLAN import org.wordpress.android.ui.domains.DomainsDashboardNavigationAction.ClaimDomain import org.wordpress.android.ui.domains.DomainsDashboardNavigationAction.GetDomain +import org.wordpress.android.ui.domains.DomainsDashboardNavigationAction.GetPlan import org.wordpress.android.ui.utils.UiHelpers import org.wordpress.android.util.config.DomainManagementFeatureConfig import org.wordpress.android.util.extensions.getSerializableExtraCompat @@ -103,6 +105,11 @@ class DomainsDashboardFragment : Fragment(R.layout.domains_dashboard_fragment), action.site, CTA_DOMAIN_CREDIT_REDEMPTION ) + is GetPlan -> ActivityLauncher.viewDomainRegistrationActivityForResult( + this, + action.site, + FREE_DOMAIN_WITH_ANNUAL_PLAN + ) } @Suppress("DEPRECATION", "OVERRIDE_DEPRECATION") diff --git a/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardItem.kt index 6bf01edec646..20fc8e283c66 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardItem.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardItem.kt @@ -8,6 +8,7 @@ import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.DOMAIN_BLURB import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.MANAGE_DOMAINS import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.PRIMARY_DOMAIN import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.PURCHASE_DOMAIN +import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.PURCHASE_PLAN import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.SITE_DOMAINS import org.wordpress.android.ui.domains.DomainsDashboardItem.Type.SITE_DOMAINS_HEADER import org.wordpress.android.ui.utils.ListItemInteraction @@ -21,7 +22,8 @@ sealed class DomainsDashboardItem(val type: Type) { ADD_DOMAIN, MANAGE_DOMAINS, PURCHASE_DOMAIN, - DOMAIN_BLURB + DOMAIN_BLURB, + PURCHASE_PLAN } data class FreeDomain( @@ -49,6 +51,14 @@ sealed class DomainsDashboardItem(val type: Type) { val onClick: ListItemInteraction ) : DomainsDashboardItem(PURCHASE_DOMAIN) + data class PurchasePlan( + @DrawableRes val image: Int?, + val title: UiString, + val body: UiString, + val onUpgradeClick: ListItemInteraction, + val onDomainClick: ListItemInteraction + ) : DomainsDashboardItem(PURCHASE_PLAN) + data class DomainBlurb(val blurb: UiString) : DomainsDashboardItem(DOMAIN_BLURB) enum class Action(@IdRes val itemId: Int) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardNavigationAction.kt b/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardNavigationAction.kt index 733ceff0ebe9..60d32b8105d5 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardNavigationAction.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardNavigationAction.kt @@ -5,4 +5,5 @@ import org.wordpress.android.fluxc.model.SiteModel sealed class DomainsDashboardNavigationAction { data class GetDomain(val site: SiteModel) : DomainsDashboardNavigationAction() data class ClaimDomain(val site: SiteModel) : DomainsDashboardNavigationAction() + data class GetPlan(val site: SiteModel) : DomainsDashboardNavigationAction() } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardViewHolder.kt index 9aaeca1cf0b4..02e5db36518b 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardViewHolder.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardViewHolder.kt @@ -10,6 +10,7 @@ import org.wordpress.android.R import org.wordpress.android.databinding.DomainAddDomainCtaBinding import org.wordpress.android.databinding.DomainFreeSiteAddressCardBinding import org.wordpress.android.databinding.DomainManageDomainsCtaBinding +import org.wordpress.android.databinding.DomainPlanPurchaseCardBinding import org.wordpress.android.databinding.DomainPurchaseCardBinding import org.wordpress.android.databinding.DomainSiteDomainsBlurbBinding import org.wordpress.android.databinding.DomainSiteDomainsCardBinding @@ -21,6 +22,7 @@ import org.wordpress.android.ui.domains.DomainsDashboardItem.ManageDomains import org.wordpress.android.ui.domains.DomainsDashboardItem.PurchaseDomain import org.wordpress.android.ui.domains.DomainsDashboardItem.SiteDomains import org.wordpress.android.ui.domains.DomainsDashboardItem.SiteDomainsHeader +import org.wordpress.android.ui.domains.DomainsDashboardItem.PurchasePlan import org.wordpress.android.ui.utils.UiHelpers import org.wordpress.android.util.extensions.viewBinding @@ -109,6 +111,21 @@ sealed class DomainsDashboardViewHolder( } } + class PurchasePlanViewHolder( + parent: ViewGroup, + private val uiHelpers: UiHelpers + ) : DomainsDashboardViewHolder( + parent.viewBinding(DomainPlanPurchaseCardBinding::inflate) + ) { + fun onBind(item: PurchasePlan) = with(binding) { + uiHelpers.setImageOrHide(purchasePlanImage, item.image) + uiHelpers.setTextOrHide(purchasePlanTitle, item.title) + uiHelpers.setTextOrHide(purchasePlanCaption, item.body) + upgradePlanButton.setOnClickListener { item.onUpgradeClick.click() } + justSearchDomainButton.setOnClickListener { item.onDomainClick.click() } + } + } + class DomainBlurbViewHolder( parent: ViewGroup, private val uiHelpers: UiHelpers diff --git a/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardViewModel.kt index 2fb9f16c5e69..2f2305005aa9 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/domains/DomainsDashboardViewModel.kt @@ -7,6 +7,7 @@ import kotlinx.coroutines.async import org.wordpress.android.R import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAINS_DASHBOARD_ADD_DOMAIN_TAPPED import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAINS_DASHBOARD_GET_DOMAIN_TAPPED +import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAINS_DASHBOARD_GET_PLAN_TAPPED import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAINS_DASHBOARD_VIEWED import org.wordpress.android.analytics.AnalyticsTracker.Stat.DOMAIN_CREDIT_REDEMPTION_TAPPED import org.wordpress.android.fluxc.model.PlanModel @@ -22,8 +23,10 @@ import org.wordpress.android.ui.domains.DomainsDashboardItem.FreeDomain import org.wordpress.android.ui.domains.DomainsDashboardItem.PurchaseDomain import org.wordpress.android.ui.domains.DomainsDashboardItem.SiteDomains import org.wordpress.android.ui.domains.DomainsDashboardItem.SiteDomainsHeader +import org.wordpress.android.ui.domains.DomainsDashboardItem.PurchasePlan import org.wordpress.android.ui.domains.DomainsDashboardNavigationAction.ClaimDomain import org.wordpress.android.ui.domains.DomainsDashboardNavigationAction.GetDomain +import org.wordpress.android.ui.domains.DomainsDashboardNavigationAction.GetPlan import org.wordpress.android.ui.domains.usecases.FetchPlansUseCase import org.wordpress.android.ui.plans.isDomainCreditAvailable import org.wordpress.android.ui.utils.HtmlMessageUtils @@ -156,15 +159,11 @@ class DomainsDashboardViewModel @Inject constructor( ListItemInteraction.create(this::onGetDomainClick) ) } else { - PurchaseDomain( - R.drawable.img_illustration_domains_card_header, + PurchasePlan( + R.drawable.browser_address_bar, UiStringRes(R.string.domains_free_plan_get_your_domain_title), - UiStringText( - htmlMessageUtils.getHtmlMessageFromStringFormatResId( - R.string.domains_free_plan_get_your_domain_caption, - freeDomainUrl - ) - ), + UiStringRes(R.string.domains_upgrade_to_plan_caption), + ListItemInteraction.create(this::onGetPlanClick), ListItemInteraction.create(this::onGetDomainClick) ) } @@ -207,6 +206,11 @@ class DomainsDashboardViewModel @Inject constructor( _onNavigation.value = Event(GetDomain(site)) } + private fun onGetPlanClick() { + analyticsTrackerWrapper.track(DOMAINS_DASHBOARD_GET_PLAN_TAPPED, site) + _onNavigation.value = Event(GetPlan(site)) + } + private fun onClaimDomainClick() { analyticsTrackerWrapper.track(DOMAIN_CREDIT_REDEMPTION_TAPPED, site) _onNavigation.value = Event(ClaimDomain(site)) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/common/viewholders/JetpackButtonViewHolder.kt b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/common/viewholders/JetpackButtonViewHolder.kt index dfbac2af8514..b46ca1ed92ab 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/jetpack/common/viewholders/JetpackButtonViewHolder.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/jetpack/common/viewholders/JetpackButtonViewHolder.kt @@ -3,7 +3,7 @@ package org.wordpress.android.ui.jetpack.common.viewholders import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.constraintlayout.widget.ConstraintLayout +import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams import androidx.viewbinding.ViewBinding import com.google.android.material.button.MaterialButton import org.wordpress.android.R @@ -13,7 +13,6 @@ import org.wordpress.android.ui.jetpack.common.JetpackListItemState import org.wordpress.android.ui.jetpack.common.JetpackListItemState.ActionButtonState import org.wordpress.android.ui.utils.UiHelpers import org.wordpress.android.util.extensions.setVisible -import org.wordpress.android.widgets.FlowLayout.LayoutParams sealed class JetpackButtonViewHolder( parent: ViewGroup, @@ -61,9 +60,9 @@ sealed class JetpackButtonViewHolder( with(root) { setVisible(isVisible) layoutParams = if (isVisible) { - ConstraintLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) + LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT) } else { - ConstraintLayout.LayoutParams(0, 0) + LayoutParams(0, 0) } } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserActivity.java index b5d349130163..520773af12f0 100755 --- a/WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/media/MediaBrowserActivity.java @@ -113,6 +113,7 @@ public class MediaBrowserActivity extends LocaleAwareActivity implements MediaGr WPMediaUtils.LaunchCameraCallback { public static final String ARG_BROWSER_TYPE = "media_browser_type"; public static final String ARG_FILTER = "filter"; + public static final String ARG_LAUNCH_PHOTO_PICKER = "launch_photo_picker"; public static final String RESULT_IDS = "result_ids"; private static final String SAVED_QUERY = "SAVED_QUERY"; @@ -152,6 +153,8 @@ public class MediaBrowserActivity extends LocaleAwareActivity implements MediaGr private boolean mShowAudioTab; + private boolean mLaunchPhotoPicker = false; + private enum AddMenuItem { ITEM_CAPTURE_PHOTO, ITEM_CAPTURE_VIDEO, @@ -163,19 +166,20 @@ private enum AddMenuItem { @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - ((WordPress) getApplication()).component().inject(this); if (savedInstanceState == null) { mSite = (SiteModel) getIntent().getSerializableExtra(WordPress.SITE); mBrowserType = (MediaBrowserType) getIntent().getSerializableExtra(ARG_BROWSER_TYPE); mShowAudioTab = mMediaStore.getSiteAudio(mSite).size() > 0; + mLaunchPhotoPicker = getIntent().getBooleanExtra(ARG_LAUNCH_PHOTO_PICKER, false); } else { mSite = (SiteModel) savedInstanceState.getSerializable(WordPress.SITE); mBrowserType = (MediaBrowserType) savedInstanceState.getSerializable(ARG_BROWSER_TYPE); mMediaCapturePath = savedInstanceState.getString(BUNDLE_MEDIA_CAPTURE_PATH); mQuery = savedInstanceState.getString(SAVED_QUERY); mShowAudioTab = savedInstanceState.getBoolean(SHOW_AUDIO_TAB); + mLaunchPhotoPicker = savedInstanceState.getBoolean(ARG_LAUNCH_PHOTO_PICKER); } if (mSite == null) { @@ -240,6 +244,11 @@ public void onCreate(@Nullable Bundle savedInstanceState) { mQuotaText = findViewById(R.id.quota_text); showQuota(true); + + if (mLaunchPhotoPicker) { + doAddMediaItemClicked(AddMenuItem.ITEM_CHOOSE_FILE); + mLaunchPhotoPicker = false; + } } @Override @@ -417,7 +426,6 @@ public void onStart() { @Override protected void onPause() { super.onPause(); - if (mSearchMenuItem != null) { String tempQuery = mQuery; MenuItemCompat.collapseActionView(mSearchMenuItem); @@ -449,7 +457,6 @@ protected void onDestroy() { @Override protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); - outState.putString(SAVED_QUERY, mQuery); outState.putSerializable(WordPress.SITE, mSite); outState.putSerializable(ARG_BROWSER_TYPE, mBrowserType); @@ -460,6 +467,7 @@ protected void onSaveInstanceState(@NonNull Bundle outState) { if (!TextUtils.isEmpty(mMediaCapturePath)) { outState.putString(BUNDLE_MEDIA_CAPTURE_PATH, mMediaCapturePath); } + outState.putBoolean(ARG_LAUNCH_PHOTO_PICKER, mLaunchPhotoPicker); } private void getMediaFromDeviceAndTrack(Uri videoUri, int requestCode) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteCardAndItem.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteCardAndItem.kt index 6efef9ec148a..81026f4db9a4 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteCardAndItem.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteCardAndItem.kt @@ -400,16 +400,17 @@ sealed class MySiteCardAndItem(open val type: Type, open val activeQuickStartIte sealed class ActionSource { abstract val url: String - abstract val onCtaClick: ListItemInteraction + abstract val onCardClick: ListItemInteraction data class Card( override val url: String, - override val onCtaClick: ListItemInteraction + override val onCardClick: ListItemInteraction ) : ActionSource() - data class Button( + data class CardOrButton( override val url: String, - override val onCtaClick: ListItemInteraction, + override val onCardClick: ListItemInteraction, + val onButtonClick: ListItemInteraction, val title: String ) : ActionSource() } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteCardAndItemBuilderParams.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteCardAndItemBuilderParams.kt index ec761509ef6c..4c5d617f30da 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteCardAndItemBuilderParams.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteCardAndItemBuilderParams.kt @@ -51,7 +51,7 @@ sealed class MySiteCardAndItemBuilderParams { data class QuickStartCardBuilderParams( val quickStartCategories: List, val onQuickStartTaskTypeItemClick: (type: QuickStartTaskType) -> Unit, - val moreMenuClickParams : MoreMenuParams + val moreMenuClickParams: MoreMenuParams ) : MySiteCardAndItemBuilderParams() { data class MoreMenuParams( val onMoreMenuClick: (type: QuickStartCardType) -> Unit, @@ -71,13 +71,13 @@ sealed class MySiteCardAndItemBuilderParams { val pagesCardBuilderParams: PagesCardBuilderParams, val activityCardBuilderParams: ActivityCardBuilderParams, val dynamicCardsBuilderParams: DynamicCardsBuilderParams, - ) : MySiteCardAndItemBuilderParams() + ) : MySiteCardAndItemBuilderParams() data class TodaysStatsCardBuilderParams( val todaysStatsCard: TodaysStatsCardModel?, val onTodaysStatsCardClick: () -> Unit, val onGetMoreViewsClick: () -> Unit, - val moreMenuClickParams : MoreMenuParams + val moreMenuClickParams: MoreMenuParams ) : MySiteCardAndItemBuilderParams() { data class MoreMenuParams( val onMoreMenuClick: () -> Unit, @@ -89,12 +89,13 @@ sealed class MySiteCardAndItemBuilderParams { data class PostCardBuilderParams( val posts: PostsCardModel?, val onPostItemClick: (params: PostItemClickParams) -> Unit, - val moreMenuClickParams : MoreMenuParams + val moreMenuClickParams: MoreMenuParams ) : MySiteCardAndItemBuilderParams() { data class PostItemClickParams( val postCardType: PostCardType, val postId: Int ) + data class MoreMenuParams( val onMoreMenuClick: (postCardType: PostCardType) -> Unit, val onHideThisMenuItemClick: (postCardType: PostCardType) -> Unit, @@ -106,7 +107,7 @@ sealed class MySiteCardAndItemBuilderParams { val pageCard: PagesCardModel?, val onPagesItemClick: (params: PagesItemClickParams) -> Unit, val onFooterLinkClick: () -> Unit, - val moreMenuClickParams : MoreMenuParams + val moreMenuClickParams: MoreMenuParams ) : MySiteCardAndItemBuilderParams() { data class PagesItemClickParams( val pagesCardType: PagesCardContentType, @@ -162,15 +163,17 @@ sealed class MySiteCardAndItemBuilderParams { data class DynamicCardsBuilderParams( val dynamicCards: DynamicCardsModel?, - val onActionClick: (actionUrl: String) -> Unit, - val onMoreMenuClick: (cardId: String) -> Unit, + val onCtaClick: (params: ClickParams) -> Unit, + val onCardClick: (params: ClickParams) -> Unit, val onHideMenuItemClick: (cardId: String) -> Unit - ) : MySiteCardAndItemBuilderParams() + ) : MySiteCardAndItemBuilderParams() { + data class ClickParams(val id: String, val actionUrl: String) + } sealed class BlazeCardBuilderParams : MySiteCardAndItemBuilderParams() { data class PromoteWithBlazeCardBuilderParams( val onClick: () -> Unit, - val moreMenuParams : MoreMenuParams + val moreMenuParams: MoreMenuParams ) : BlazeCardBuilderParams() { data class MoreMenuParams( val onMoreMenuClick: () -> Unit, diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteFragment.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteFragment.kt index 4f74c8ca71f6..debb2b7b5aab 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteFragment.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteFragment.kt @@ -29,8 +29,10 @@ import org.wordpress.android.ui.FullScreenDialogFragment import org.wordpress.android.ui.PagePostCreationSourcesDetail import org.wordpress.android.ui.RequestCodes import org.wordpress.android.ui.TextInputDialogFragment +import org.wordpress.android.ui.WPWebViewActivity import org.wordpress.android.ui.accounts.LoginEpilogueActivity import org.wordpress.android.ui.bloganuary.learnmore.BloganuaryNudgeLearnMoreOverlayFragment +import org.wordpress.android.ui.deeplinks.DeepLinkingIntentReceiverActivity import org.wordpress.android.ui.domains.DomainRegistrationActivity import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureFullScreenOverlayFragment import org.wordpress.android.ui.jetpackoverlay.JetpackFeatureRemovalOverlayUtil @@ -65,6 +67,7 @@ import org.wordpress.android.ui.utils.UiString import org.wordpress.android.util.AppLog import org.wordpress.android.util.HtmlCompatWrapper import org.wordpress.android.util.NetworkUtils +import org.wordpress.android.util.PackageManagerWrapper import org.wordpress.android.util.QuickStartUtilsWrapper import org.wordpress.android.util.SnackbarItem import org.wordpress.android.util.SnackbarSequencer @@ -130,6 +133,9 @@ class MySiteFragment : Fragment(R.layout.my_site_fragment), @Inject lateinit var activityNavigator: ActivityNavigator + @Inject + lateinit var packageManagerWrapper: PackageManagerWrapper + private lateinit var viewModel: MySiteViewModel private lateinit var dialogViewModel: BasicDialogViewModel private lateinit var wpMainActivityViewModel: WPMainActivityViewModel @@ -665,6 +671,10 @@ class MySiteFragment : Fragment(R.layout.my_site_fragment), ActivityLauncher.viewBlogStatsForTimeframe(requireActivity(), action.site, StatsTimeframe.INSIGHTS) is SiteNavigationAction.OpenExternalUrl -> ActivityLauncher.openUrlExternal(requireActivity(), action.url) + is SiteNavigationAction.OpenUrlInWebView -> + WPWebViewActivity.openURL(requireActivity(), action.url) + is SiteNavigationAction.OpenDeepLink -> + DeepLinkingIntentReceiverActivity.openDeepLinkUrl(requireActivity(), action.url) is SiteNavigationAction.OpenJetpackPoweredBottomSheet -> showJetpackPoweredBottomSheet() is SiteNavigationAction.OpenJetpackMigrationDeleteWP -> showJetpackMigrationDeleteWP() is SiteNavigationAction.OpenJetpackFeatureOverlay -> showJetpackFeatureOverlay(action.source) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt index 68af2a267ddf..2c51f7655bc6 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/MySiteViewModel.kt @@ -234,6 +234,7 @@ class MySiteViewModel @Inject constructor( siteInfoHeaderCardViewModelSlice.onNavigation, quickLinksItemViewModelSlice.navigation, sotw2023NudgeCardViewModelSlice.onNavigation, + dynamicCardsViewModelSlice.onNavigation, ) val onMediaUpload = siteInfoHeaderCardViewModelSlice.onMediaUpload @@ -250,6 +251,7 @@ class MySiteViewModel @Inject constructor( activityLogCardViewModelSlice.refresh, bloganuaryNudgeCardViewModelSlice.refresh, sotw2023NudgeCardViewModelSlice.refresh, + dynamicCardsViewModelSlice.refresh, ) private var shouldMarkUpdateSiteTitleTaskComplete = false @@ -992,6 +994,8 @@ class MySiteViewModel @Inject constructor( .forEach { noCardsMessageViewModelSlice.trackShown(it.type) } siteSelected.dashboardData.filterIsInstance() .forEach { _ -> sotw2023NudgeCardViewModelSlice.trackShown() } + siteSelected.dashboardData.filterIsInstance() + .forEach { dynamicCardsViewModelSlice.trackShown(it.id) } } private fun resetShownTrackers() { @@ -1002,6 +1006,7 @@ class MySiteViewModel @Inject constructor( jetpackInstallFullPluginShownTracker.resetShown() personalizeCardViewModelSlice.resetShown() sotw2023NudgeCardViewModelSlice.resetShown() + dynamicCardsViewModelSlice.resetShown() } // FluxC events diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt index 4fbeb52c0d1f..4fbfff996878 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/SiteNavigationAction.kt @@ -86,6 +86,8 @@ sealed class SiteNavigationAction { data class EditScheduledPost(val site: SiteModel, val postId: Int) : SiteNavigationAction() data class OpenStatsInsights(val site: SiteModel) : SiteNavigationAction() data class OpenExternalUrl(val url: String) : SiteNavigationAction() + data class OpenUrlInWebView(val url: String) : SiteNavigationAction() + data class OpenDeepLink(val url: String) : SiteNavigationAction() object OpenJetpackPoweredBottomSheet : SiteNavigationAction() object OpenJetpackMigrationDeleteWP : SiteNavigationAction() data class OpenJetpackFeatureOverlay(val source: JetpackFeatureCollectionOverlaySource) : SiteNavigationAction() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/CardsSource.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/CardsSource.kt index 9339b1d9abe8..33b3aa292daa 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/CardsSource.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dashboard/CardsSource.kt @@ -118,7 +118,7 @@ class CardsSource @Inject constructor( } private fun shouldRequestDynamicCards(): Boolean { - return dynamicDashboardCardsFeatureConfig.isEnabled() // TODO We should also add check for hidden cards here + return dynamicDashboardCardsFeatureConfig.isEnabled() } private fun MediatorLiveData.postErrorState() { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardComposable.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardComposable.kt index ab9556785b06..caa92fd07216 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardComposable.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardComposable.kt @@ -22,13 +22,13 @@ fun DynamicDashboardCard( UnelevatedCard( modifier = modifier .run { - if (card.action is ActionSource.Card) clickable { card.action.onCtaClick.click() } else this + if (card.action != null) clickable { card.action.onCardClick.click() } else this }, content = { Column( - Modifier.padding(top = 8.dp, bottom = 8.dp) + Modifier.padding(bottom = 8.dp) ) { - val isCtaInvisible = card.action !is ActionSource.Button + val isCtaInvisible = card.action !is ActionSource.CardOrButton DynamicCardHeader( title = card.title, onHideMenuClicked = { card.onHideMenuItemClick.click() } @@ -47,8 +47,8 @@ fun DynamicDashboardCard( modifier = Modifier.run { if (isCtaInvisible) padding(bottom = 8.dp) else this } ) } - (card.action as? ActionSource.Button)?.title?.let { title -> - DynamicCardCallToActionButton(text = title, onClicked = { card.action.onCtaClick.click() }) + (card.action as? ActionSource.CardOrButton)?.title?.let { title -> + DynamicCardCallToActionButton(text = title, onClicked = { card.action.onButtonClick.click() }) } } } @@ -65,9 +65,10 @@ fun DynamicDashboardCardPreview() { id = "id", title = "Card Title", image = "https://picsum.photos/200/300", - action = ActionSource.Button( + action = ActionSource.CardOrButton( title = "Call to Action", url = "", - onCtaClick = ListItemInteraction.create {}, + onCardClick = ListItemInteraction.create {}, + onButtonClick = ListItemInteraction.create {}, ), rows = listOf( MySiteCardAndItem.Card.Dynamic.Row( @@ -96,10 +97,11 @@ fun DynamicDashboardCardWithFeatureAndDescriptionPreview() { id = "id", title = null, image = "https://picsum.photos/200/300", - action = ActionSource.Button( + action = ActionSource.CardOrButton( title = "See yours now", url = "", - onCtaClick = ListItemInteraction.create {}, + onCardClick = ListItemInteraction.create {}, + onButtonClick = ListItemInteraction.create {}, ), rows = listOf( MySiteCardAndItem.Card.Dynamic.Row( @@ -124,10 +126,11 @@ fun DynamicDashboardCardWithFeatureAndSubtitleAndDescriptionPreview() { id = "id", title = null, image = "https://picsum.photos/200/300", - action = ActionSource.Button( + action = ActionSource.CardOrButton( title = "Find out more", url = "", - onCtaClick = ListItemInteraction.create {}, + onCardClick = ListItemInteraction.create {}, + onButtonClick = ListItemInteraction.create {}, ), rows = listOf( MySiteCardAndItem.Card.Dynamic.Row( @@ -154,7 +157,7 @@ fun DynamicDashboardCardWithNoCta() { image = "https://picsum.photos/200/300", action = ActionSource.Card( url = "", - onCtaClick = ListItemInteraction.create {}, + onCardClick = ListItemInteraction.create {}, ), rows = listOf( MySiteCardAndItem.Card.Dynamic.Row( @@ -181,7 +184,7 @@ fun DynamicDashboardWithFeatureImageOnly() { image = "https://picsum.photos/200/300", action = ActionSource.Card( url = "", - onCtaClick = ListItemInteraction.create {}, + onCardClick = ListItemInteraction.create {}, ), rows = listOf(), onHideMenuItemClick = ListItemInteraction.create {}, @@ -199,9 +202,10 @@ fun DynamicDashboardCardWithTitleAndCompleteRowsPreview() { id = "id", title = "What's New in Jetpack", image = null, - action = ActionSource.Button( + action = ActionSource.CardOrButton( title = "Find out more", url = "", - onCtaClick = ListItemInteraction.create {}, + onCardClick = ListItemInteraction.create {}, + onButtonClick = ListItemInteraction.create {}, ), rows = listOf( MySiteCardAndItem.Card.Dynamic.Row( diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardFeatureImage.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardFeatureImage.kt index 9aed8495a37f..86736c54e285 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardFeatureImage.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardFeatureImage.kt @@ -6,13 +6,16 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.composed import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.painter.ColorPainter import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import org.wordpress.android.ui.compose.theme.AppColor + @Composable fun DynamicCardFeatureImage(imageUrl: String, modifier: Modifier = Modifier) { AsyncImage( @@ -24,6 +27,10 @@ fun DynamicCardFeatureImage(imageUrl: String, modifier: Modifier = Modifier) { .padding(start = 16.dp, end = 16.dp) .clip(RoundedCornerShape(6.dp)) .fillMaxWidth() - .aspectRatio(2f) + .previewAspectRatio(2f) ) } + +private fun Modifier.previewAspectRatio(ratio: Float): Modifier = composed { + if (LocalInspectionMode.current) aspectRatio(ratio) else this +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardHeader.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardHeader.kt index f6dcbb711854..be2838e43c7d 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardHeader.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardHeader.kt @@ -1,23 +1,16 @@ package org.wordpress.android.ui.mysite.cards.dynamiccard import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material.ContentAlpha -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.MoreVert -import androidx.compose.material.Icon -import androidx.compose.material.IconButton -import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import org.wordpress.android.R import org.wordpress.android.ui.compose.styles.DashboardCardTypography +import org.wordpress.android.ui.mysite.cards.compose.MySiteCardToolbar +import org.wordpress.android.ui.mysite.cards.compose.MySiteCardToolbarContextMenuItem @Composable fun DynamicCardHeader( @@ -25,12 +18,16 @@ fun DynamicCardHeader( onHideMenuClicked: () -> Unit, modifier: Modifier = Modifier, ) { - Row( - modifier = modifier.padding(start = 16.dp, end = 16.dp, bottom = 8.dp), - verticalAlignment = Alignment.CenterVertically + MySiteCardToolbar( + modifier = modifier.padding(bottom = 8.dp), + contextMenuItems = listOf( + MySiteCardToolbarContextMenuItem.Option( + text = stringResource(R.string.my_site_dashboard_card_more_menu_hide_card), + onClick = onHideMenuClicked, + ) + ), ) { Title(title = title, modifier = Modifier.weight(1f)) - Menu(onHideMenuClicked) } } @@ -45,17 +42,3 @@ private fun Title(title: String?, modifier: Modifier = Modifier) { } ) } - -@Composable -private fun Menu(onHideMenuClicked: () -> Unit) { - IconButton( - modifier = Modifier.size(32.dp), - onClick = onHideMenuClicked - ) { - Icon( - imageVector = Icons.Rounded.MoreVert, - contentDescription = stringResource(id = R.string.more), - tint = MaterialTheme.colors.onSurface.copy(alpha = ContentAlpha.medium), - ) - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsAnalyticsTracker.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsAnalyticsTracker.kt new file mode 100644 index 000000000000..88249d3fcfb3 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsAnalyticsTracker.kt @@ -0,0 +1,52 @@ +package org.wordpress.android.ui.mysite.cards.dynamiccard + +import org.wordpress.android.analytics.AnalyticsTracker.Stat.DYNAMIC_DASHBOARD_CARD_CTA_TAPPED +import org.wordpress.android.analytics.AnalyticsTracker.Stat.DYNAMIC_DASHBOARD_CARD_HIDE_TAPPED +import org.wordpress.android.analytics.AnalyticsTracker.Stat.DYNAMIC_DASHBOARD_CARD_SHOWN +import org.wordpress.android.analytics.AnalyticsTracker.Stat.DYNAMIC_DASHBOARD_CARD_TAPPED +import org.wordpress.android.util.analytics.AnalyticsTrackerWrapper +import javax.inject.Inject + +private const val CARD_PROPERTY_ID = "id" +private const val CARD_PROPERTY_URL = "url" + +class DynamicCardsAnalyticsTracker @Inject constructor( + private val analyticsTracker: AnalyticsTrackerWrapper, +) { + private var cardShownTracked = mutableListOf() + + fun resetShown() { + cardShownTracked = mutableListOf() + } + + fun trackShown(id: String) { + if (!cardShownTracked.contains(id)) { + cardShownTracked.add(id) + analyticsTracker.track( + stat = DYNAMIC_DASHBOARD_CARD_SHOWN, + properties = mapOf(CARD_PROPERTY_ID to id) + ) + } + } + + fun trackCardTapped(id: String, url: String) { + analyticsTracker.track( + stat = DYNAMIC_DASHBOARD_CARD_TAPPED, + properties = mapOf(CARD_PROPERTY_ID to id, CARD_PROPERTY_URL to url) + ) + } + + fun trackCtaTapped(id: String, url: String) { + analyticsTracker.track( + stat = DYNAMIC_DASHBOARD_CARD_CTA_TAPPED, + properties = mapOf(CARD_PROPERTY_ID to id, CARD_PROPERTY_URL to url) + ) + } + + fun trackHideTapped(id: String) { + analyticsTracker.track( + stat = DYNAMIC_DASHBOARD_CARD_HIDE_TAPPED, + properties = mapOf(CARD_PROPERTY_ID to id) + ) + } +} diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsBuilder.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsBuilder.kt index 23712cf6bbd0..646052113207 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsBuilder.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsBuilder.kt @@ -1,33 +1,35 @@ package org.wordpress.android.ui.mysite.cards.dynamiccard -import org.wordpress.android.fluxc.model.dashboard.CardModel import org.wordpress.android.fluxc.model.dashboard.CardModel.DynamicCardsModel.CardOrder +import org.wordpress.android.fluxc.model.dashboard.CardModel.DynamicCardsModel.DynamicCardModel import org.wordpress.android.ui.deeplinks.handlers.DeepLinkHandlers import org.wordpress.android.ui.mysite.MySiteCardAndItem.Card.Dynamic import org.wordpress.android.ui.mysite.MySiteCardAndItemBuilderParams.DynamicCardsBuilderParams -import org.wordpress.android.ui.utils.ListItemInteraction.Companion.create -import org.wordpress.android.util.UriWrapper +import org.wordpress.android.ui.utils.ListItemInteraction import org.wordpress.android.util.UrlUtilsWrapper +import org.wordpress.android.util.config.DynamicDashboardCardsFeatureConfig +import org.wordpress.android.util.config.FeatureFlagConfig import javax.inject.Inject class DynamicCardsBuilder @Inject constructor( private val urlUtils: UrlUtilsWrapper, - private val deepLinkHandlers: DeepLinkHandlers + private val deepLinkHandlers: DeepLinkHandlers, + private val dynamicDashboardCardsFeatureConfig: DynamicDashboardCardsFeatureConfig, + private val featureFlagConfig: FeatureFlagConfig, ) { fun build(params: DynamicCardsBuilderParams, order: CardOrder): List? { - if (!shouldBuildCard(params, order)) { + if (!dynamicDashboardCardsFeatureConfig.isEnabled() || !shouldBuildCard(params, order)) { return null } return convertToDynamicCards(params, order) } private fun shouldBuildCard(params: DynamicCardsBuilderParams, order: CardOrder): Boolean { - if (params.dynamicCards == null || params.dynamicCards.pages.none { it.order == order }) return false - return true + return !(params.dynamicCards == null || params.dynamicCards.dynamicCards.none { it.order == order }) } private fun convertToDynamicCards(params: DynamicCardsBuilderParams, order: CardOrder): List { - val cards = params.dynamicCards?.pages?.filter { it.order == order } ?: emptyList() + val cards = params.dynamicCards?.dynamicCards?.filter { it.order == order && it.isEnabled() }.orEmpty() return cards.map { card -> Dynamic( id = card.id, @@ -41,30 +43,48 @@ class DynamicCardsBuilder @Inject constructor( title = card.title, image = card.featuredImage, action = getActionSource(params, card), - onHideMenuItemClick = create(card.id, params.onHideMenuItemClick), + onHideMenuItemClick = ListItemInteraction.create(card.id, params.onHideMenuItemClick), ) } } + fun DynamicCardModel.isEnabled(): Boolean { + // If there is no feature flag or there is no such remote feature flag, then the card is enabled + if (remoteFeatureFlag.isNullOrEmpty() || + featureFlagConfig.getString(requireNotNull(remoteFeatureFlag)).isEmpty() + ) return true + return featureFlagConfig.isEnabled(requireNotNull(remoteFeatureFlag)) + } + private fun getActionSource( params: DynamicCardsBuilderParams, - card: CardModel.DynamicCardsModel.DynamicCardModel + card: DynamicCardModel ): Dynamic.ActionSource? = when { - isValidUrlOrDeeplink(card.url) && isValidActionTitle(card.action) -> Dynamic.ActionSource.Button( - requireNotNull(card.url), - create(requireNotNull(card.url), params.onActionClick), - requireNotNull(card.action) + isValidUrlOrDeeplink(card.url) && isValidActionTitle(card.action) -> Dynamic.ActionSource.CardOrButton( + url = requireNotNull(card.url), + title = requireNotNull(card.action), + onCardClick = ListItemInteraction.create( + data = DynamicCardsBuilderParams.ClickParams(id = card.id, actionUrl = requireNotNull(card.url)), + action = params.onCardClick + ), + onButtonClick = ListItemInteraction.create( + data = DynamicCardsBuilderParams.ClickParams(id = card.id, actionUrl = requireNotNull(card.url)), + action = params.onCtaClick + ) ) isValidUrlOrDeeplink(card.url) -> Dynamic.ActionSource.Card( - requireNotNull(card.url), - create(requireNotNull(card.url), params.onActionClick) + url = requireNotNull(card.url), + onCardClick = ListItemInteraction.create( + data = DynamicCardsBuilderParams.ClickParams(id = card.id, actionUrl = requireNotNull(card.url)), + action = params.onCardClick + ) ) else -> null } private fun isValidUrlOrDeeplink(url: String?): Boolean { return !url.isNullOrEmpty() && (urlUtils.isValidUrlAndHostNotNull(url) - || deepLinkHandlers.buildNavigateAction(UriWrapper(url)) != null) + || deepLinkHandlers.isDeepLink(url)) } private fun isValidActionTitle(title: String?): Boolean { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsViewModelSlice.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsViewModelSlice.kt index 8def20febd51..0be5c0531121 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsViewModelSlice.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/cards/dynamiccard/DynamicCardsViewModelSlice.kt @@ -3,39 +3,65 @@ package org.wordpress.android.ui.mysite.cards.dynamiccard import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import org.wordpress.android.fluxc.model.dashboard.CardModel +import org.wordpress.android.ui.deeplinks.handlers.DeepLinkHandlers import org.wordpress.android.ui.mysite.MySiteCardAndItemBuilderParams.DynamicCardsBuilderParams import org.wordpress.android.ui.mysite.SiteNavigationAction -import org.wordpress.android.util.AppLog +import org.wordpress.android.ui.prefs.AppPrefsWrapper import org.wordpress.android.viewmodel.Event import javax.inject.Inject -class DynamicCardsViewModelSlice @Inject constructor() { +class DynamicCardsViewModelSlice @Inject constructor( + private val appPrefsWrapper: AppPrefsWrapper, + private val deepLinkHandlers: DeepLinkHandlers, + private val tracker: DynamicCardsAnalyticsTracker, +) { private val _onNavigation = MutableLiveData>() val onNavigation = _onNavigation as LiveData> private val _refresh = MutableLiveData>() val refresh = _refresh as LiveData> + fun getBuilderParams(dynamicCards: CardModel.DynamicCardsModel?): DynamicCardsBuilderParams { return DynamicCardsBuilderParams( - dynamicCards = dynamicCards, - onActionClick = this::onActionClick, - onMoreMenuClick = this::onMoreMenuClick, + dynamicCards = dynamicCards?.filterVisible(), + onCardClick = { onCardClick(id = it.id, actionUrl = it.actionUrl) }, + onCtaClick = { onCtaClick(id = it.id, actionUrl = it.actionUrl) }, onHideMenuItemClick = this::onHideMenuItemClick ) } - private fun onActionClick(actionUrl: String) { - AppLog.d(AppLog.T.MY_SITE_DASHBOARD, "Dynamic dashboard card action clicked: $actionUrl") - // TODO + private fun onCardClick(id: String, actionUrl: String) { + tracker.trackCardTapped(id = id, url = actionUrl) + onActionClick(actionUrl) } - private fun onMoreMenuClick(cardId: String) { - AppLog.d(AppLog.T.MY_SITE_DASHBOARD, "Dynamic dashboard card action more menu click: $cardId") - // TODO + private fun onCtaClick(id: String, actionUrl: String) { + tracker.trackCtaTapped(id = id, url = actionUrl) + onActionClick(actionUrl) + } + + private fun onActionClick(actionUrl: String) { + if (deepLinkHandlers.isDeepLink(actionUrl)) { + _onNavigation.value = Event(SiteNavigationAction.OpenDeepLink(actionUrl)) + } else { + _onNavigation.value = Event(SiteNavigationAction.OpenUrlInWebView(actionUrl)) + } } private fun onHideMenuItemClick(cardId: String) { - AppLog.d(AppLog.T.MY_SITE_DASHBOARD, "Dynamic dashboard card action hide menu click: $cardId") - // TODO + tracker.trackHideTapped(cardId) + appPrefsWrapper.setShouldHideDynamicCard(cardId, true) + _refresh.value = Event(true) + } + + private fun CardModel.DynamicCardsModel.filterVisible(): CardModel.DynamicCardsModel = + copy(dynamicCards = dynamicCards.filterNot { appPrefsWrapper.getShouldHideDynamicCard(it.id) }) + + fun trackShown(id: String) { + tracker.trackShown(id) + } + + fun resetShown() { + tracker.resetShown() } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/pages/PagesListActions.kt b/WordPress/src/main/java/org/wordpress/android/ui/pages/PagesListActions.kt index 84f60df0dfe3..d830cbca6552 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/pages/PagesListActions.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/pages/PagesListActions.kt @@ -56,7 +56,7 @@ enum class PagesListAction( actionGroup = ActionGroup.TAKE_AN_ACTION, positionInGroup = 7, ), - COPY_LINK( + SHARE( R.string.button_share, R.drawable.gb_ic_share, actionGroup = ActionGroup.SHARE_AND_PROMOTE, diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/AppPrefs.java b/WordPress/src/main/java/org/wordpress/android/ui/prefs/AppPrefs.java index f66e0418093e..a9d199817ab2 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/AppPrefs.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/AppPrefs.java @@ -210,6 +210,7 @@ public enum DeletablePrefKey implements PrefKey { SHOULD_SHOW_DEFAULT_QUICK_LINK_IN_DASHBOARD, SHOULD_HIDE_BLOGANUARY_NUDGE_CARD, SHOULD_HIDE_SOTW2023_NUDGE_CARD, + SHOULD_HIDE_DYNAMIC_CARD, } /** @@ -1836,4 +1837,12 @@ public static void setShouldHideSotw2023NudgeCard(boolean isHidden) { public static boolean getShouldHideSotw2023NudgeCard() { return prefs().getBoolean(DeletablePrefKey.SHOULD_HIDE_SOTW2023_NUDGE_CARD.name(), false); } + + public static void setShouldHideDynamicCard(@NonNull final String id, final boolean isHidden) { + prefs().edit().putBoolean(DeletablePrefKey.SHOULD_HIDE_DYNAMIC_CARD.name() + id, isHidden).apply(); + } + + public static boolean getShouldHideDynamicCard(@NonNull final String id) { + return prefs().getBoolean(DeletablePrefKey.SHOULD_HIDE_DYNAMIC_CARD.name() + id, false); + } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/prefs/AppPrefsWrapper.kt b/WordPress/src/main/java/org/wordpress/android/ui/prefs/AppPrefsWrapper.kt index 307e6772e1ff..10b8ef20cd04 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/prefs/AppPrefsWrapper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/prefs/AppPrefsWrapper.kt @@ -434,6 +434,12 @@ class AppPrefsWrapper @Inject constructor() { fun getShouldHideSotw2023NudgeCard(): Boolean = AppPrefs.getShouldHideSotw2023NudgeCard() + fun setShouldHideDynamicCard(id: String, isHidden: Boolean): Unit = + AppPrefs.setShouldHideDynamicCard(id, isHidden) + + fun getShouldHideDynamicCard(id: String, ): Boolean = + AppPrefs.getShouldHideDynamicCard(id) + fun getAllPrefs(): Map = AppPrefs.getAllPrefs() fun setString(prefKey: PrefKey, value: String) { diff --git a/WordPress/src/main/java/org/wordpress/android/viewmodel/pages/CreatePageListItemActionsUseCase.kt b/WordPress/src/main/java/org/wordpress/android/viewmodel/pages/CreatePageListItemActionsUseCase.kt index d1915e03d7cb..0f423138c45d 100644 --- a/WordPress/src/main/java/org/wordpress/android/viewmodel/pages/CreatePageListItemActionsUseCase.kt +++ b/WordPress/src/main/java/org/wordpress/android/viewmodel/pages/CreatePageListItemActionsUseCase.kt @@ -5,7 +5,6 @@ import org.wordpress.android.fluxc.model.SiteModel import org.wordpress.android.ui.pages.PagesListAction import org.wordpress.android.ui.pages.PagesListAction.CANCEL_AUTO_UPLOAD import org.wordpress.android.ui.pages.PagesListAction.COPY -import org.wordpress.android.ui.pages.PagesListAction.COPY_LINK import org.wordpress.android.ui.pages.PagesListAction.DELETE_PERMANENTLY import org.wordpress.android.ui.pages.PagesListAction.MOVE_TO_DRAFT import org.wordpress.android.ui.pages.PagesListAction.MOVE_TO_TRASH @@ -14,6 +13,7 @@ import org.wordpress.android.ui.pages.PagesListAction.PUBLISH_NOW import org.wordpress.android.ui.pages.PagesListAction.SET_AS_HOMEPAGE import org.wordpress.android.ui.pages.PagesListAction.SET_AS_POSTS_PAGE import org.wordpress.android.ui.pages.PagesListAction.SET_PARENT +import org.wordpress.android.ui.pages.PagesListAction.SHARE import org.wordpress.android.ui.pages.PagesListAction.VIEW_PAGE import org.wordpress.android.viewmodel.pages.PageListViewModel.PageListType import org.wordpress.android.viewmodel.pages.PageListViewModel.PageListType.DRAFTS @@ -57,7 +57,7 @@ class CreatePageListItemActionsUseCase @Inject constructor() { return mutableListOf( VIEW_PAGE, SET_PARENT, - COPY_LINK, + SHARE, MOVE_TO_DRAFT, MOVE_TO_TRASH ).apply { @@ -81,7 +81,7 @@ class CreatePageListItemActionsUseCase @Inject constructor() { return mutableListOf( VIEW_PAGE, COPY, - COPY_LINK, + SHARE, SET_PARENT ).apply { if (siteModel.isUsingWpComRestApi && @@ -112,7 +112,7 @@ class CreatePageListItemActionsUseCase @Inject constructor() { } private fun getDraftsPageActions(uploadUiState: PostUploadUiState): List { - return mutableListOf(VIEW_PAGE, SET_PARENT, PUBLISH_NOW, MOVE_TO_TRASH, COPY, COPY_LINK).apply { + return mutableListOf(VIEW_PAGE, SET_PARENT, PUBLISH_NOW, MOVE_TO_TRASH, COPY, SHARE).apply { if (canCancelPendingAutoUpload(uploadUiState)) { add(CANCEL_AUTO_UPLOAD) } diff --git a/WordPress/src/main/java/org/wordpress/android/viewmodel/pages/PagesViewModel.kt b/WordPress/src/main/java/org/wordpress/android/viewmodel/pages/PagesViewModel.kt index 3a361e03f105..a87d5625e2b3 100644 --- a/WordPress/src/main/java/org/wordpress/android/viewmodel/pages/PagesViewModel.kt +++ b/WordPress/src/main/java/org/wordpress/android/viewmodel/pages/PagesViewModel.kt @@ -43,7 +43,6 @@ import org.wordpress.android.ui.pages.PagesAuthorFilterUIState import org.wordpress.android.ui.pages.PagesListAction import org.wordpress.android.ui.pages.PagesListAction.CANCEL_AUTO_UPLOAD import org.wordpress.android.ui.pages.PagesListAction.COPY -import org.wordpress.android.ui.pages.PagesListAction.COPY_LINK import org.wordpress.android.ui.pages.PagesListAction.DELETE_PERMANENTLY import org.wordpress.android.ui.pages.PagesListAction.MOVE_TO_DRAFT import org.wordpress.android.ui.pages.PagesListAction.MOVE_TO_TRASH @@ -52,6 +51,7 @@ import org.wordpress.android.ui.pages.PagesListAction.PUBLISH_NOW import org.wordpress.android.ui.pages.PagesListAction.SET_AS_HOMEPAGE import org.wordpress.android.ui.pages.PagesListAction.SET_AS_POSTS_PAGE import org.wordpress.android.ui.pages.PagesListAction.SET_PARENT +import org.wordpress.android.ui.pages.PagesListAction.SHARE import org.wordpress.android.ui.pages.PagesListAction.VIEW_PAGE import org.wordpress.android.ui.pages.SnackbarMessageHolder import org.wordpress.android.ui.posts.AuthorFilterListItemUIState @@ -473,7 +473,7 @@ class PagesViewModel SET_AS_HOMEPAGE -> setHomepage(page.remoteId) SET_AS_POSTS_PAGE -> setPostsPage(page.remoteId) COPY -> onCopyPage(page) - COPY_LINK -> context?.let { copyPageLink(page, it) } + SHARE -> context?.let { copyPageLink(page, it) } PROMOTE_WITH_BLAZE -> navigateToBlazeOverlay(page.remoteId) } return true @@ -572,6 +572,7 @@ class PagesViewModel private fun copyPageLink(page: Page, context: Context) { // Get the link to the page + trackMenuSelectionEvent(SHARE) val pageLink = postStore.getPostByLocalPostId(page.localId)?.link ?: return ActivityLauncher.openShareIntent( context, @@ -658,7 +659,7 @@ class PagesViewModel MOVE_TO_DRAFT -> "move_to_draft" DELETE_PERMANENTLY -> "delete_permanently" MOVE_TO_TRASH -> "move_to_bin" - COPY_LINK -> "copy_link" + SHARE -> "share" PROMOTE_WITH_BLAZE -> "promote_with_blaze" } val properties = mutableMapOf("option_name" to menu as Any) diff --git a/WordPress/src/main/java/org/wordpress/android/widgets/AutoCompleteEmptyTextView.java b/WordPress/src/main/java/org/wordpress/android/widgets/AutoCompleteEmptyTextView.java deleted file mode 100644 index 368afc50c09a..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/widgets/AutoCompleteEmptyTextView.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.wordpress.android.widgets; - -import android.content.Context; -import android.util.AttributeSet; - -import androidx.appcompat.widget.AppCompatAutoCompleteTextView; - -public class AutoCompleteEmptyTextView extends AppCompatAutoCompleteTextView { - public AutoCompleteEmptyTextView(Context context) { - super(context); - } - - public AutoCompleteEmptyTextView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public AutoCompleteEmptyTextView(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - @Override - public boolean enoughToFilter() { - return true; - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/widgets/ContextMenuEditText.java b/WordPress/src/main/java/org/wordpress/android/widgets/ContextMenuEditText.java deleted file mode 100644 index e50cfb828e18..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/widgets/ContextMenuEditText.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.wordpress.android.widgets; - -import android.content.Context; -import android.util.AttributeSet; - -import androidx.appcompat.widget.AppCompatEditText; - -/** - * EditText which notifies when text is cut, copied, or pasted. - */ -public class ContextMenuEditText extends AppCompatEditText { - public interface OnContextMenuListener { - void onCut(); - - void onCopy(); - - void onPaste(); - } - - private OnContextMenuListener mOnContextMenuListener; - - /** - * Set a listener to interface with activity or fragment. - * - * @param listener object listening for cut, copy, and paste events - */ - public void setOnContextMenuListener(OnContextMenuListener listener) { - mOnContextMenuListener = listener; - } - - public ContextMenuEditText(Context context) { - super(context); - } - - public ContextMenuEditText(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ContextMenuEditText(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - /** - * ContextMenu used to cut, copy, or paste which overwrites the consuming method. - */ - @Override - public boolean onTextContextMenuItem(int id) { - boolean consumed = super.onTextContextMenuItem(id); - - switch (id) { - case android.R.id.cut: - onCut(); - break; - case android.R.id.copy: - onCopy(); - break; - case android.R.id.paste: - onPaste(); - break; - } - - return consumed; - } - - /** - * Text cut from EditText. - */ - public void onCut() { - if (mOnContextMenuListener != null) { - mOnContextMenuListener.onCut(); - } - } - - /** - * Text copied from EditText. - */ - public void onCopy() { - if (mOnContextMenuListener != null) { - mOnContextMenuListener.onCopy(); - } - } - - /** - * Text pasted into EditText. - */ - public void onPaste() { - if (mOnContextMenuListener != null) { - mOnContextMenuListener.onPaste(); - } - } -} diff --git a/WordPress/src/main/java/org/wordpress/android/widgets/FlowLayout.java b/WordPress/src/main/java/org/wordpress/android/widgets/FlowLayout.java deleted file mode 100644 index fe76a6eb6d4e..000000000000 --- a/WordPress/src/main/java/org/wordpress/android/widgets/FlowLayout.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Sample FlowLayout wrote by Romain Guy: http://www.parleys.com/play/514892280364bc17fc56c0e2/chapter38/about - * Fixed and tweaked since - */ - -package org.wordpress.android.widgets; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; - -import androidx.core.view.ViewCompat; - -import org.wordpress.android.R; - -public class FlowLayout extends ViewGroup { - private int mHorizontalSpacing; - private int mVerticalSpacing; - - public FlowLayout(Context context, AttributeSet attrs) { - super(context, attrs); - - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout); - try { - mHorizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_horizontalSpacing, 0); - mVerticalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_verticalSpacing, 0); - } finally { - a.recycle(); - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthSize = MeasureSpec.getSize(widthMeasureSpec) - ViewCompat.getPaddingEnd(this) - ViewCompat - .getPaddingStart(this); - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - - boolean growHeight = widthMode != MeasureSpec.UNSPECIFIED; - - int width = 0; - int height = getPaddingTop(); - - int currentWidth = ViewCompat.getPaddingStart(this); - int currentHeight = 0; - - boolean newLine = false; - int spacing = 0; - - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - View child = getChildAt(i); - measureChild(child, widthMeasureSpec, heightMeasureSpec); - - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - spacing = mHorizontalSpacing; - if (lp.horizontalSpacing >= 0) { - spacing = lp.horizontalSpacing; - } - - if (growHeight && currentWidth + child.getMeasuredWidth() > widthSize) { - height += currentHeight + mVerticalSpacing; - currentHeight = 0; - width = Math.max(width, currentWidth - spacing); - currentWidth = ViewCompat.getPaddingStart(this); - newLine = true; - } else { - newLine = false; - } - - lp.x = currentWidth; - lp.y = height; - - currentWidth += child.getMeasuredWidth() + spacing; - currentHeight = Math.max(currentHeight, child.getMeasuredHeight()); - } - - if (!newLine) { - width = Math.max(width, currentWidth - spacing); - } - width += ViewCompat.getPaddingEnd(this); - height += currentHeight + getPaddingBottom(); - - setMeasuredDimension(resolveSize(width, widthMeasureSpec), resolveSize(height, heightMeasureSpec)); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - View child = getChildAt(i); - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - - if (ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL) { - child.layout(child.getMeasuredWidth() - lp.x - child.getMeasuredWidth(), lp.y, r - lp.x, - lp.y + child.getMeasuredHeight()); - } else { - child.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y + child.getMeasuredHeight()); - } - } - } - - @Override - protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { - return p instanceof LayoutParams; - } - - @Override - protected LayoutParams generateDefaultLayoutParams() { - return new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); - } - - @Override - public LayoutParams generateLayoutParams(AttributeSet attrs) { - return new LayoutParams(getContext(), attrs); - } - - @Override - protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { - return new LayoutParams(p.width, p.height); - } - - public static class LayoutParams extends ViewGroup.MarginLayoutParams { - public int x; - public int y; - public int horizontalSpacing; - - public LayoutParams(Context context, AttributeSet attrs) { - super(context, attrs); - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FlowLayout_Layout); - try { - horizontalSpacing = a.getDimensionPixelSize(R.styleable.FlowLayout_Layout_layout_horizontalSpacing, -1); - } finally { - a.recycle(); - } - } - - public LayoutParams(int w, int h) { - super(w, h); - } - } -} diff --git a/WordPress/src/main/res/drawable/bg_oval_transparent_stroke_on_surface_lowest.xml b/WordPress/src/main/res/drawable/bg_oval_transparent_stroke_on_surface_lowest.xml deleted file mode 100644 index f46210e51679..000000000000 --- a/WordPress/src/main/res/drawable/bg_oval_transparent_stroke_on_surface_lowest.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/WordPress/src/main/res/drawable/img_write_212dp.xml b/WordPress/src/main/res/drawable/img_write_212dp.xml deleted file mode 100644 index dc712dc0a6af..000000000000 --- a/WordPress/src/main/res/drawable/img_write_212dp.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/WordPress/src/main/res/drawable/tooltip_arrow.xml b/WordPress/src/main/res/drawable/tooltip_arrow.xml deleted file mode 100644 index 93e718fce133..000000000000 --- a/WordPress/src/main/res/drawable/tooltip_arrow.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/WordPress/src/main/res/layout/comment_activity.xml b/WordPress/src/main/res/layout/comment_activity.xml deleted file mode 100644 index f707387f02cc..000000000000 --- a/WordPress/src/main/res/layout/comment_activity.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/WordPress/src/main/res/layout/comment_list_fragment.xml b/WordPress/src/main/res/layout/comment_list_fragment.xml deleted file mode 100644 index 1b1481e1e784..000000000000 --- a/WordPress/src/main/res/layout/comment_list_fragment.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/WordPress/src/main/res/layout/debug_settings_button.xml b/WordPress/src/main/res/layout/debug_settings_button.xml deleted file mode 100644 index 1d3d3340d8f5..000000000000 --- a/WordPress/src/main/res/layout/debug_settings_button.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - diff --git a/WordPress/src/main/res/layout/debug_settings_header.xml b/WordPress/src/main/res/layout/debug_settings_header.xml deleted file mode 100644 index 84abd2eea59b..000000000000 --- a/WordPress/src/main/res/layout/debug_settings_header.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - diff --git a/WordPress/src/main/res/layout/debug_settings_row.xml b/WordPress/src/main/res/layout/debug_settings_row.xml deleted file mode 100644 index e7e6f4590a7a..000000000000 --- a/WordPress/src/main/res/layout/debug_settings_row.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/WordPress/src/main/res/layout/domain_plan_purchase_card.xml b/WordPress/src/main/res/layout/domain_plan_purchase_card.xml new file mode 100644 index 000000000000..7f1f651e50b2 --- /dev/null +++ b/WordPress/src/main/res/layout/domain_plan_purchase_card.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + diff --git a/WordPress/src/main/res/layout/jetpack_powered_animated_image.xml b/WordPress/src/main/res/layout/jetpack_powered_animated_image.xml deleted file mode 100644 index 545dd5062063..000000000000 --- a/WordPress/src/main/res/layout/jetpack_powered_animated_image.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/WordPress/src/main/res/layout/jetpack_powered_caption.xml b/WordPress/src/main/res/layout/jetpack_powered_caption.xml deleted file mode 100644 index a7a1af309ebd..000000000000 --- a/WordPress/src/main/res/layout/jetpack_powered_caption.xml +++ /dev/null @@ -1,9 +0,0 @@ - - diff --git a/WordPress/src/main/res/layout/jetpack_powered_title.xml b/WordPress/src/main/res/layout/jetpack_powered_title.xml deleted file mode 100644 index 63679d7b1a91..000000000000 --- a/WordPress/src/main/res/layout/jetpack_powered_title.xml +++ /dev/null @@ -1,11 +0,0 @@ - - diff --git a/WordPress/src/main/res/layout/me_action_layout.xml b/WordPress/src/main/res/layout/me_action_layout.xml deleted file mode 100644 index e594e9b1668d..000000000000 --- a/WordPress/src/main/res/layout/me_action_layout.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/WordPress/src/main/res/layout/my_site_card_footer_link.xml b/WordPress/src/main/res/layout/my_site_card_footer_link.xml deleted file mode 100644 index 62a0dca71d85..000000000000 --- a/WordPress/src/main/res/layout/my_site_card_footer_link.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - diff --git a/WordPress/src/main/res/layout/my_site_post_card_without_post_items.xml b/WordPress/src/main/res/layout/my_site_post_card_without_post_items.xml deleted file mode 100644 index 7b02eca87faf..000000000000 --- a/WordPress/src/main/res/layout/my_site_post_card_without_post_items.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/WordPress/src/main/res/layout/site_settings_timezone_dialog.xml b/WordPress/src/main/res/layout/site_settings_timezone_dialog.xml deleted file mode 100644 index 0f6abe599127..000000000000 --- a/WordPress/src/main/res/layout/site_settings_timezone_dialog.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/WordPress/src/main/res/layout/tooltip_above.xml b/WordPress/src/main/res/layout/tooltip_above.xml deleted file mode 100644 index a3d5b54b3424..000000000000 --- a/WordPress/src/main/res/layout/tooltip_above.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - diff --git a/WordPress/src/main/res/layout/tooltip_below.xml b/WordPress/src/main/res/layout/tooltip_below.xml deleted file mode 100644 index 6a315b17cec7..000000000000 --- a/WordPress/src/main/res/layout/tooltip_below.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - diff --git a/WordPress/src/main/res/layout/tooltip_left.xml b/WordPress/src/main/res/layout/tooltip_left.xml deleted file mode 100644 index dffb9e4ed0c5..000000000000 --- a/WordPress/src/main/res/layout/tooltip_left.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - diff --git a/WordPress/src/main/res/layout/tooltip_right.xml b/WordPress/src/main/res/layout/tooltip_right.xml deleted file mode 100644 index 8a0c20f4872b..000000000000 --- a/WordPress/src/main/res/layout/tooltip_right.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - diff --git a/WordPress/src/main/res/values-land/dimens.xml b/WordPress/src/main/res/values-land/dimens.xml index c32c067b9c5d..0a2ec43b918c 100644 --- a/WordPress/src/main/res/values-land/dimens.xml +++ b/WordPress/src/main/res/values-land/dimens.xml @@ -14,4 +14,6 @@ 16dp 12dp + 160dp + diff --git a/WordPress/src/main/res/values/attrs.xml b/WordPress/src/main/res/values/attrs.xml index 45d1a0318594..229f6d3e54a1 100644 --- a/WordPress/src/main/res/values/attrs.xml +++ b/WordPress/src/main/res/values/attrs.xml @@ -64,15 +64,6 @@ - - - - - - - - - diff --git a/WordPress/src/main/res/values/dashboard_card_styles.xml b/WordPress/src/main/res/values/dashboard_card_styles.xml index 3c3604b7309d..3b438f7ef0b0 100644 --- a/WordPress/src/main/res/values/dashboard_card_styles.xml +++ b/WordPress/src/main/res/values/dashboard_card_styles.xml @@ -41,12 +41,6 @@ end - - - - - - - - + + + + + + + + + +