diff --git a/docs/design.md b/docs/design.md index 2e27f00ebf..a79f19cf3e 100644 --- a/docs/design.md +++ b/docs/design.md @@ -50,6 +50,17 @@ It's also possible for any icon to go to the main component by right-clicking on - open the created vector drawable - optionally update the color(s) to "#FF0000" (red) to ensure that the drawable is correctly tinted at runtime. +### Images + +Android 4.3 (18+) fully supports the WebP image format which can often provide smaller image sizes without drastically impacting image quality (depending on the output encoding quality). +When importing non vector images, WebP is the preferred format. + +Images can be converted to the WebP within Android Studio by + - right clicking the image file within the project file explorer + - select `Convert to WebP` + +https://developer.android.com/studio/write/convert-webp + ## Figma links Figma links can be included in the layout, for future reference, but it is also OK to add a paragraph below here, to centralize the information diff --git a/library/ui-styles/src/main/res/drawable/bg_carousel_page_1.xml b/library/ui-styles/src/main/res/drawable/bg_carousel_page_1.xml new file mode 100644 index 0000000000..bff828fb22 --- /dev/null +++ b/library/ui-styles/src/main/res/drawable/bg_carousel_page_1.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/library/ui-styles/src/main/res/drawable/bg_carousel_page_2.xml b/library/ui-styles/src/main/res/drawable/bg_carousel_page_2.xml new file mode 100644 index 0000000000..54e5286ded --- /dev/null +++ b/library/ui-styles/src/main/res/drawable/bg_carousel_page_2.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/library/ui-styles/src/main/res/drawable/bg_carousel_page_3.xml b/library/ui-styles/src/main/res/drawable/bg_carousel_page_3.xml new file mode 100644 index 0000000000..c31c70c078 --- /dev/null +++ b/library/ui-styles/src/main/res/drawable/bg_carousel_page_3.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/library/ui-styles/src/main/res/drawable/bg_carousel_page_4.xml b/library/ui-styles/src/main/res/drawable/bg_carousel_page_4.xml new file mode 100644 index 0000000000..56989688af --- /dev/null +++ b/library/ui-styles/src/main/res/drawable/bg_carousel_page_4.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/library/ui-styles/src/main/res/values-sw600dp/dimens.xml b/library/ui-styles/src/main/res/values-sw600dp/dimens.xml index 204d663d9c..f399a350b1 100644 --- a/library/ui-styles/src/main/res/values-sw600dp/dimens.xml +++ b/library/ui-styles/src/main/res/values-sw600dp/dimens.xml @@ -2,4 +2,8 @@ 400dp + + + 0.25 + 0.75 \ No newline at end of file diff --git a/library/ui-styles/src/main/res/values/dimens.xml b/library/ui-styles/src/main/res/values/dimens.xml index 9fbf8958da..a2a6b34b0f 100644 --- a/library/ui-styles/src/main/res/values/dimens.xml +++ b/library/ui-styles/src/main/res/values/dimens.xml @@ -47,4 +47,8 @@ 56dp 52dp 1dp + + + 0.05 + 0.95 \ No newline at end of file diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt b/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt index 7ae7a53963..87d7e36ed5 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/features/DebugFeaturesStateFactory.kt @@ -16,8 +16,11 @@ package im.vector.app.features.debug.features +import androidx.datastore.preferences.core.Preferences import im.vector.app.features.DefaultVectorFeatures +import im.vector.app.features.VectorFeatures import javax.inject.Inject +import kotlin.reflect.KFunction1 class DebugFeaturesStateFactory @Inject constructor( private val debugFeatures: DebugVectorFeatures, @@ -31,18 +34,23 @@ class DebugFeaturesStateFactory @Inject constructor( featureOverride = debugFeatures.onboardingVariant(), featureDefault = defaultFeatures.onboardingVariant() ), - - Feature.BooleanFeature( + createBooleanFeature( label = "FTUE Splash - I already have an account", - featureOverride = debugFeatures.isAlreadyHaveAccountSplashEnabled().takeIf { - debugFeatures.hasOverride(DebugFeatureKeys.alreadyHaveAnAccount) - }, - featureDefault = defaultFeatures.isAlreadyHaveAccountSplashEnabled(), + factory = VectorFeatures::isAlreadyHaveAccountSplashEnabled, key = DebugFeatureKeys.alreadyHaveAnAccount ) )) } + private fun createBooleanFeature(key: Preferences.Key, label: String, factory: KFunction1): Feature { + return Feature.BooleanFeature( + label = label, + featureOverride = factory.invoke(debugFeatures).takeIf { debugFeatures.hasOverride(key) }, + featureDefault = factory.invoke(defaultFeatures), + key = key + ) + } + private inline fun > createEnumFeature(label: String, featureOverride: T, featureDefault: T): Feature { return Feature.EnumFeature( label = label, diff --git a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt index daab981956..2e11017ef3 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/features/DebugVectorFeatures.kt @@ -43,9 +43,11 @@ class DebugVectorFeatures( return readPreferences().getEnum() ?: vectorFeatures.onboardingVariant() } - override fun isAlreadyHaveAccountSplashEnabled(): Boolean = readPreferences()[DebugFeatureKeys.alreadyHaveAnAccount] + override fun isAlreadyHaveAccountSplashEnabled(): Boolean = read(DebugFeatureKeys.alreadyHaveAnAccount) ?: vectorFeatures.isAlreadyHaveAccountSplashEnabled() + override fun isSplashCarouselEnabled(): Boolean = read(DebugFeatureKeys.splashCarousel) ?: vectorFeatures.isSplashCarouselEnabled() + fun override(value: T?, key: Preferences.Key) = updatePreferences { if (value == null) { it.remove(key) @@ -66,6 +68,8 @@ class DebugVectorFeatures( } } + private fun read(key: Preferences.Key): Boolean? = readPreferences()[key] + private fun readPreferences() = runBlocking { dataStore.data.first() } private fun updatePreferences(block: (MutablePreferences) -> Unit) = runBlocking { @@ -92,6 +96,6 @@ private inline fun > enumPreferencesKey() = enumPreferencesK private fun > enumPreferencesKey(type: KClass) = stringPreferencesKey("enum-${type.simpleName}") object DebugFeatureKeys { - val alreadyHaveAnAccount = booleanPreferencesKey("already-have-an-account") + val splashCarousel = booleanPreferencesKey("splash-carousel") } diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt index 217abd495a..c27309fad6 100644 --- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt @@ -102,6 +102,7 @@ import im.vector.app.features.onboarding.ftueauth.FtueAuthResetPasswordMailConfi import im.vector.app.features.onboarding.ftueauth.FtueAuthResetPasswordSuccessFragment import im.vector.app.features.onboarding.ftueauth.FtueAuthServerSelectionFragment import im.vector.app.features.onboarding.ftueauth.FtueAuthSignUpSignInSelectionFragment +import im.vector.app.features.onboarding.ftueauth.FtueAuthSplashCarouselFragment import im.vector.app.features.onboarding.ftueauth.FtueAuthSplashFragment import im.vector.app.features.onboarding.ftueauth.FtueAuthWaitForEmailFragment import im.vector.app.features.onboarding.ftueauth.FtueAuthWebFragment @@ -443,6 +444,11 @@ interface FragmentModule { @FragmentKey(FtueAuthSplashFragment::class) fun bindFtueAuthSplashFragment(fragment: FtueAuthSplashFragment): Fragment + @Binds + @IntoMap + @FragmentKey(FtueAuthSplashCarouselFragment::class) + fun bindFtueAuthSplashCarouselFragment(fragment: FtueAuthSplashCarouselFragment): Fragment + @Binds @IntoMap @FragmentKey(FtueAuthWaitForEmailFragment::class) diff --git a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt index 0349b15c4d..c53ff0f433 100644 --- a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt +++ b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt @@ -24,19 +24,17 @@ interface VectorFeatures { fun isAlreadyHaveAccountSplashEnabled(): Boolean + fun isSplashCarouselEnabled(): Boolean + enum class OnboardingVariant { LEGACY, LOGIN_2, FTUE_AUTH } - - enum class NotificationSettingsVersion { - V1, - V2 - } } class DefaultVectorFeatures : VectorFeatures { override fun onboardingVariant(): VectorFeatures.OnboardingVariant = BuildConfig.ONBOARDING_VARIANT override fun isAlreadyHaveAccountSplashEnabled() = true + override fun isSplashCarouselEnabled() = false } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingVariantFactory.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingVariantFactory.kt index 5f861d8808..c171fc223d 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingVariantFactory.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingVariantFactory.kt @@ -36,7 +36,8 @@ class OnboardingVariantFactory @Inject constructor( views = views, onboardingViewModel = onboardingViewModel.value, activity = activity, - supportFragmentManager = activity.supportFragmentManager + supportFragmentManager = activity.supportFragmentManager, + vectorFeatures = vectorFeatures ) VectorFeatures.OnboardingVariant.LOGIN_2 -> Login2Variant( views = views, diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt new file mode 100644 index 0000000000..f89ae36eb6 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSplashCarouselFragment.kt @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.onboarding.ftueauth + +import android.annotation.SuppressLint +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.view.isVisible +import com.airbnb.mvrx.withState +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.google.android.material.tabs.TabLayoutMediator +import im.vector.app.BuildConfig +import im.vector.app.R +import im.vector.app.databinding.FragmentFtueSplashCarouselBinding +import im.vector.app.features.VectorFeatures +import im.vector.app.features.onboarding.OnboardingAction +import im.vector.app.features.onboarding.OnboardingFlow +import im.vector.app.features.settings.VectorPreferences +import org.matrix.android.sdk.api.failure.Failure +import java.net.UnknownHostException +import javax.inject.Inject + +class FtueAuthSplashCarouselFragment @Inject constructor( + private val vectorPreferences: VectorPreferences, + private val vectorFeatures: VectorFeatures, + private val carouselController: SplashCarouselController +) : AbstractFtueAuthFragment() { + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueSplashCarouselBinding { + return FragmentFtueSplashCarouselBinding.inflate(inflater, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + setupViews() + } + + private fun setupViews() { + views.splashCarousel.adapter = carouselController.adapter + TabLayoutMediator(views.carouselIndicator, views.splashCarousel) { _, _ -> }.attach() + carouselController.setData(SplashCarouselState()) + + views.loginSplashSubmit.debouncedClicks { getStarted() } + views.loginSplashAlreadyHaveAccount.apply { + isVisible = vectorFeatures.isAlreadyHaveAccountSplashEnabled() + debouncedClicks { alreadyHaveAnAccount() } + } + + if (BuildConfig.DEBUG || vectorPreferences.developerMode()) { + views.loginSplashVersion.isVisible = true + @SuppressLint("SetTextI18n") + views.loginSplashVersion.text = "Version : ${BuildConfig.VERSION_NAME}#${BuildConfig.BUILD_NUMBER}\n" + + "Branch: ${BuildConfig.GIT_BRANCH_NAME}" + views.loginSplashVersion.debouncedClicks { navigator.openDebug(requireContext()) } + } + } + + private fun getStarted() { + val getStartedFlow = if (vectorFeatures.isAlreadyHaveAccountSplashEnabled()) OnboardingFlow.SignUp else OnboardingFlow.SignInSignUp + viewModel.handle(OnboardingAction.OnGetStarted(resetLoginConfig = false, onboardingFlow = getStartedFlow)) + } + + private fun alreadyHaveAnAccount() { + viewModel.handle(OnboardingAction.OnIAlreadyHaveAnAccount(resetLoginConfig = false, onboardingFlow = OnboardingFlow.SignIn)) + } + + override fun resetViewModel() { + // Nothing to do + } + + override fun onError(throwable: Throwable) { + if (throwable is Failure.NetworkConnection && + throwable.ioException is UnknownHostException) { + // Invalid homeserver from URL config + val url = viewModel.getInitialHomeServerUrl().orEmpty() + MaterialAlertDialogBuilder(requireActivity()) + .setTitle(R.string.dialog_title_error) + .setMessage(getString(R.string.login_error_homeserver_from_url_not_found, url)) + .setPositiveButton(R.string.login_error_homeserver_from_url_not_found_enter_manual) { _, _ -> + val flow = withState(viewModel) { it.onboardingFlow } ?: OnboardingFlow.SignInSignUp + viewModel.handle(OnboardingAction.OnGetStarted(resetLoginConfig = true, flow)) + } + .setNegativeButton(R.string.action_cancel, null) + .show() + } else { + super.onError(throwable) + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt index f17899dff6..f177eda114 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt @@ -15,7 +15,6 @@ */ package im.vector.app.features.onboarding.ftueauth - import android.content.Intent import android.view.View import android.view.ViewGroup @@ -34,6 +33,7 @@ import im.vector.app.core.extensions.addFragmentToBackstack import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.databinding.ActivityLoginBinding +import im.vector.app.features.VectorFeatures import im.vector.app.features.home.HomeActivity import im.vector.app.features.login.LoginConfig import im.vector.app.features.login.LoginMode @@ -61,7 +61,8 @@ class FtueAuthVariant( private val views: ActivityLoginBinding, private val onboardingViewModel: OnboardingViewModel, private val activity: VectorBaseActivity, - private val supportFragmentManager: FragmentManager + private val supportFragmentManager: FragmentManager, + private val vectorFeatures: VectorFeatures ) : OnboardingVariant { private val enterAnim = R.anim.enter_fade_in @@ -108,7 +109,11 @@ class FtueAuthVariant( } private fun addFirstFragment() { - activity.addFragment(views.loginFragmentContainer, FtueAuthSplashFragment::class.java) + val splashFragment = when (vectorFeatures.isSplashCarouselEnabled()) { + true -> FtueAuthSplashCarouselFragment::class.java + else -> FtueAuthSplashFragment::class.java + } + activity.addFragment(views.loginFragmentContainer, splashFragment) } private fun handleOnboardingViewEvents(viewEvents: OnboardingViewEvents) { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWaitForEmailFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWaitForEmailFragment.kt index a90d919c05..94758c7fad 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWaitForEmailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWaitForEmailFragment.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 New Vector Ltd + * Copyright 2019 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselController.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselController.kt new file mode 100644 index 0000000000..95df0a6eed --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselController.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.onboarding.ftueauth + +import com.airbnb.epoxy.TypedEpoxyController +import javax.inject.Inject + +class SplashCarouselController @Inject constructor() : TypedEpoxyController() { + override fun buildModels(data: SplashCarouselState) { + data.items.forEachIndexed { index, item -> + splashCarouselItem { + id(index) + item(item) + } + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselItem.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselItem.kt new file mode 100644 index 0000000000..1230d8109a --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselItem.kt @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.onboarding.ftueauth + +import android.widget.ImageView +import android.widget.TextView +import com.airbnb.epoxy.EpoxyAttribute +import com.airbnb.epoxy.EpoxyModelClass +import im.vector.app.R +import im.vector.app.core.epoxy.VectorEpoxyHolder +import im.vector.app.core.epoxy.VectorEpoxyModel + +@EpoxyModelClass(layout = R.layout.item_splash_carousel) +abstract class SplashCarouselItem : VectorEpoxyModel() { + + @EpoxyAttribute + lateinit var item: SplashCarouselState.Item + + override fun bind(holder: Holder) { + super.bind(holder) + + holder.view.setBackgroundResource(item.pageBackground) + holder.image.setImageResource(item.image) + holder.title.setText(item.title) + holder.body.setText(item.body) + } + + class Holder : VectorEpoxyHolder() { + val image by bind(R.id.carousel_item_image) + val title by bind(R.id.carousel_item_title) + val body by bind(R.id.carousel_item_body) + } +} diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselState.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselState.kt new file mode 100644 index 0000000000..c86e78d139 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/SplashCarouselState.kt @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.onboarding.ftueauth + +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import im.vector.app.R + +data class SplashCarouselState( + val items: List = listOf( + Item( + R.string.ftue_auth_carousel_1_title, + R.string.ftue_auth_carousel_1_body, + R.drawable.onboarding_carousel_conversations, + R.drawable.bg_carousel_page_1 + ), + Item( + R.string.ftue_auth_carousel_2_title, + R.string.ftue_auth_carousel_2_body, + R.drawable.onboarding_carousel_ems, + R.drawable.bg_carousel_page_2 + ), + Item( + R.string.ftue_auth_carousel_3_title, + R.string.ftue_auth_carousel_3_body, + R.drawable.onboarding_carousel_connect, + R.drawable.bg_carousel_page_3 + ), + Item( + R.string.ftue_auth_carousel_4_title, + R.string.ftue_auth_carousel_4_body, + R.drawable.onboarding_carousel_universal, + R.drawable.bg_carousel_page_4 + ) + ) +) { + data class Item( + @StringRes val title: Int, + @StringRes val body: Int, + @DrawableRes val image: Int, + @DrawableRes val pageBackground: Int + ) +} diff --git a/vector/src/main/res/drawable-xhdpi/onboarding_carousel_connect.webp b/vector/src/main/res/drawable-xhdpi/onboarding_carousel_connect.webp new file mode 100644 index 0000000000..50aa2bc0f0 Binary files /dev/null and b/vector/src/main/res/drawable-xhdpi/onboarding_carousel_connect.webp differ diff --git a/vector/src/main/res/drawable-xhdpi/onboarding_carousel_conversations.webp b/vector/src/main/res/drawable-xhdpi/onboarding_carousel_conversations.webp new file mode 100644 index 0000000000..cb1038db14 Binary files /dev/null and b/vector/src/main/res/drawable-xhdpi/onboarding_carousel_conversations.webp differ diff --git a/vector/src/main/res/drawable-xhdpi/onboarding_carousel_ems.webp b/vector/src/main/res/drawable-xhdpi/onboarding_carousel_ems.webp new file mode 100644 index 0000000000..4f1754b300 Binary files /dev/null and b/vector/src/main/res/drawable-xhdpi/onboarding_carousel_ems.webp differ diff --git a/vector/src/main/res/drawable-xhdpi/onboarding_carousel_universal.webp b/vector/src/main/res/drawable-xhdpi/onboarding_carousel_universal.webp new file mode 100644 index 0000000000..de4c5f18cf Binary files /dev/null and b/vector/src/main/res/drawable-xhdpi/onboarding_carousel_universal.webp differ diff --git a/vector/src/main/res/drawable/indicator_onboarding_carousel_inactive.xml b/vector/src/main/res/drawable/indicator_onboarding_carousel_inactive.xml new file mode 100644 index 0000000000..cdc99d6718 --- /dev/null +++ b/vector/src/main/res/drawable/indicator_onboarding_carousel_inactive.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/vector/src/main/res/drawable/indicator_onboarding_carousel_selected.xml b/vector/src/main/res/drawable/indicator_onboarding_carousel_selected.xml new file mode 100644 index 0000000000..46aeb80298 --- /dev/null +++ b/vector/src/main/res/drawable/indicator_onboarding_carousel_selected.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/vector/src/main/res/drawable/indicator_onboarding_carousel_selector.xml b/vector/src/main/res/drawable/indicator_onboarding_carousel_selector.xml new file mode 100644 index 0000000000..03249ff429 --- /dev/null +++ b/vector/src/main/res/drawable/indicator_onboarding_carousel_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/vector/src/main/res/layout/fragment_ftue_splash.xml b/vector/src/main/res/layout/fragment_ftue_splash.xml new file mode 100644 index 0000000000..f38bbc049e --- /dev/null +++ b/vector/src/main/res/layout/fragment_ftue_splash.xml @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +