mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2274 Payments | Design | Layout for screens with membership details (#992)
This commit is contained in:
parent
fe71de374f
commit
8c6dce6f8f
16 changed files with 624 additions and 97 deletions
11
core-ui/src/main/res/drawable/ic_check_16.xml
Normal file
11
core-ui/src/main/res/drawable/ic_check_16.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="16dp"
|
||||
android:height="17dp"
|
||||
android:viewportWidth="16"
|
||||
android:viewportHeight="17">
|
||||
<path
|
||||
android:pathData="M3,8.688L7,12.688L13,3.688"
|
||||
android:strokeWidth="1.25"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="@color/text_primary"/>
|
||||
</vector>
|
59
core-ui/src/main/res/drawable/logo_builder_96.xml
Normal file
59
core-ui/src/main/res/drawable/logo_builder_96.xml
Normal file
|
@ -0,0 +1,59 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="96dp"
|
||||
android:height="97dp"
|
||||
android:viewportWidth="96"
|
||||
android:viewportHeight="97">
|
||||
<path
|
||||
android:pathData="M26.4,27.353m0,26.4a26.4,26.4 0,1 1,0 -52.8a26.4,26.4 0,1 1,0 52.8">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="26.4"
|
||||
android:centerY="27.353"
|
||||
android:gradientRadius="26.4"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#00A5AEFF"/>
|
||||
<item android:offset="1" android:color="#FFA5AEFF"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M26.4,70.553m0,26.4a26.4,26.4 0,1 1,0 -52.8a26.4,26.4 0,1 1,0 52.8">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="26.4"
|
||||
android:centerY="70.553"
|
||||
android:gradientRadius="26.4"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#00A5AEFF"/>
|
||||
<item android:offset="1" android:color="#FFA5AEFF"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M69.6,27.353m0,26.4a26.4,26.4 0,1 1,0 -52.8a26.4,26.4 0,1 1,0 52.8">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="69.6"
|
||||
android:centerY="27.353"
|
||||
android:gradientRadius="26.4"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#00A5AEFF"/>
|
||||
<item android:offset="1" android:color="#FFA5AEFF"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M69.6,70.553m0,26.4a26.4,26.4 0,1 1,0 -52.8a26.4,26.4 0,1 1,0 52.8">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="69.6"
|
||||
android:centerY="70.553"
|
||||
android:gradientRadius="26.4"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#00A5AEFF"/>
|
||||
<item android:offset="1" android:color="#FFA5AEFF"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</vector>
|
131
core-ui/src/main/res/drawable/logo_co_creator_96.xml
Normal file
131
core-ui/src/main/res/drawable/logo_co_creator_96.xml
Normal file
|
@ -0,0 +1,131 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="96dp"
|
||||
android:height="97dp"
|
||||
android:viewportWidth="96"
|
||||
android:viewportHeight="97">
|
||||
<group>
|
||||
<clip-path
|
||||
android:pathData="M0,0.126h96v96h-96z"/>
|
||||
<path
|
||||
android:pathData="M48.001,20.123m0,20a20,20 0,1 1,0 -40a20,20 0,1 1,0 40"
|
||||
android:strokeAlpha="0.6"
|
||||
android:fillAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="48.001"
|
||||
android:centerY="20.123"
|
||||
android:gradientRadius="20"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#00F05F5F"/>
|
||||
<item android:offset="1" android:color="#FFF05F5F"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M48.001,76.126m0,20a20,20 0,1 1,0 -40a20,20 0,1 1,0 40"
|
||||
android:strokeAlpha="0.6"
|
||||
android:fillAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="48.001"
|
||||
android:centerY="76.126"
|
||||
android:gradientRadius="20"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#00F05F5F"/>
|
||||
<item android:offset="1" android:color="#FFF05F5F"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M20,48.12m20,-0a20,20 0,1 1,-40 -0a20,20 0,1 1,40 -0"
|
||||
android:strokeAlpha="0.6"
|
||||
android:fillAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="20"
|
||||
android:centerY="48.12"
|
||||
android:gradientRadius="20"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#00F05F5F"/>
|
||||
<item android:offset="1" android:color="#FFF05F5F"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M76,48.12m20,-0a20,20 0,1 1,-40 -0a20,20 0,1 1,40 -0"
|
||||
android:strokeAlpha="0.6"
|
||||
android:fillAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="76"
|
||||
android:centerY="48.12"
|
||||
android:gradientRadius="20"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#00F05F5F"/>
|
||||
<item android:offset="1" android:color="#FFF05F5F"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M14.059,14.18C21.869,6.37 34.533,6.37 42.343,14.18C50.154,21.99 50.154,34.654 42.343,42.464C34.533,50.275 21.869,50.275 14.059,42.464C6.249,34.654 6.249,21.99 14.059,14.18Z"
|
||||
android:strokeAlpha="0.6"
|
||||
android:fillAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="28.201"
|
||||
android:centerY="28.322"
|
||||
android:gradientRadius="20"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#00F05F5F"/>
|
||||
<item android:offset="1" android:color="#FFF05F5F"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M53.658,53.781C61.468,45.97 74.132,45.97 81.942,53.781C89.753,61.591 89.753,74.254 81.942,82.065C74.132,89.875 61.468,89.875 53.658,82.065C45.847,74.254 45.847,61.591 53.658,53.781Z"
|
||||
android:strokeAlpha="0.6"
|
||||
android:fillAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="67.8"
|
||||
android:centerY="67.923"
|
||||
android:gradientRadius="20"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#00F05F5F"/>
|
||||
<item android:offset="1" android:color="#FFF05F5F"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M14.057,82.062C6.247,74.252 6.247,61.588 14.057,53.778C21.868,45.967 34.531,45.967 42.342,53.778C50.152,61.588 50.152,74.252 42.342,82.062C34.531,89.872 21.868,89.872 14.057,82.062Z"
|
||||
android:strokeAlpha="0.6"
|
||||
android:fillAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="28.2"
|
||||
android:centerY="67.92"
|
||||
android:gradientRadius="20"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#00F05F5F"/>
|
||||
<item android:offset="1" android:color="#FFF05F5F"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M53.655,42.464C45.845,34.654 45.845,21.991 53.655,14.18C61.466,6.37 74.129,6.37 81.939,14.18C89.75,21.991 89.75,34.654 81.939,42.464C74.129,50.275 61.466,50.275 53.655,42.464Z"
|
||||
android:strokeAlpha="0.6"
|
||||
android:fillAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="67.797"
|
||||
android:centerY="28.322"
|
||||
android:gradientRadius="20"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#00F05F5F"/>
|
||||
<item android:offset="1" android:color="#FFF05F5F"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</group>
|
||||
</vector>
|
52
core-ui/src/main/res/drawable/logo_explorer_96.xml
Normal file
52
core-ui/src/main/res/drawable/logo_explorer_96.xml
Normal file
|
@ -0,0 +1,52 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="96dp"
|
||||
android:height="96dp"
|
||||
android:viewportWidth="96"
|
||||
android:viewportHeight="96">
|
||||
<path
|
||||
android:pathData="M48,48m-48,0a48,48 0,1 1,96 0a48,48 0,1 1,-96 0"
|
||||
android:strokeAlpha="0.4"
|
||||
android:fillAlpha="0.4">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="48"
|
||||
android:centerY="48"
|
||||
android:gradientRadius="48"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#0024BFD4"/>
|
||||
<item android:offset="1" android:color="#FF24BFD4"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M48,48.262m-26.4,0a26.4,26.4 0,1 1,52.8 0a26.4,26.4 0,1 1,-52.8 0"
|
||||
android:strokeAlpha="0.6"
|
||||
android:fillAlpha="0.6">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="48"
|
||||
android:centerY="48.262"
|
||||
android:gradientRadius="26.4"
|
||||
android:type="radial">
|
||||
<item android:offset="0.41" android:color="#0024BFD4"/>
|
||||
<item android:offset="1" android:color="#FF24BFD4"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:pathData="M48,48.263m-6,0a6,6 0,1 1,12 0a6,6 0,1 1,-12 0"
|
||||
android:strokeAlpha="0.8"
|
||||
android:fillAlpha="0.8">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:centerX="48"
|
||||
android:centerY="48.263"
|
||||
android:gradientRadius="6"
|
||||
android:type="radial">
|
||||
<item android:offset="0.285" android:color="#002AAFC1"/>
|
||||
<item android:offset="1" android:color="#FF2AAFC1"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
</vector>
|
|
@ -1368,4 +1368,40 @@
|
|||
<string name="payments_let_us_link_start">Would you like to use Anytype for business, education, etc.?</string>
|
||||
<string name="payments_let_us_link_end">Please let us know here.</string>
|
||||
|
||||
<!-- Membership Level Details -->
|
||||
<string name="payments_details_name_title">Pick your unique name</string>
|
||||
<string name="payments_details_name_subtitle">This name acts like a personal domain, making it easier for others to find you</string>
|
||||
<string name="payments_details_name_hint">Myself</string>
|
||||
<string name="payments_details_name_domain">.any</string>
|
||||
<string name="payments_details_name_error">This name is already taken!</string>
|
||||
<string name="payments_details_name_success">This name is up for grabs!</string>
|
||||
|
||||
<string name="payments_details_info_explorer">Dive into the network and enjoy the thrill of one-on-one collaboration</string>
|
||||
<string-array name="payments_benefits_explorer">
|
||||
<item>1 GB of network space</item>
|
||||
<item>10 one-to-one spaces</item>
|
||||
<item>Up to 10 shared spaces in read-only mode</item>
|
||||
</string-array>
|
||||
|
||||
<string name="payments_details_info_builder">Unlock the magic of multi-party collaboration and enjoy top-notch support</string>
|
||||
<string-array name="payments_benefits_builder">
|
||||
<item>Unique name (from 7 characters)</item>
|
||||
<item>128 GB of network space</item>
|
||||
<item>10 Guest collaborator seats</item>
|
||||
<item>Priority support</item>
|
||||
</string-array>
|
||||
|
||||
<string name="payments_details_info_cocreator">Support our adventure and unlock exclusive access and perks</string>
|
||||
<string-array name="payments_benefits_cocreator">
|
||||
<item>Unique name (from 5 characters)</item>
|
||||
<item>256 GB of network space</item>
|
||||
<item>25 Guest collaborator seats</item>
|
||||
<item>Chat with the team</item>
|
||||
<item>Unique collectible</item>
|
||||
</string-array>
|
||||
|
||||
<string name="payments_detials_button_pay">Pay by Card</string>
|
||||
<string name="payments_detials_button_submit">Submit</string>
|
||||
<string name="payments_details_whats_included">What’s included</string>
|
||||
|
||||
</resources>
|
30
payments/src/main/java/com/anytypeio/anytype/models/Tier.kt
Normal file
30
payments/src/main/java/com/anytypeio/anytype/models/Tier.kt
Normal file
|
@ -0,0 +1,30 @@
|
|||
package com.anytypeio.anytype.models
|
||||
|
||||
sealed class Tier {
|
||||
abstract val id: String
|
||||
abstract val isCurrent: Boolean
|
||||
|
||||
data class Explorer(
|
||||
override val id: String,
|
||||
override val isCurrent: Boolean,
|
||||
val price: String = ""
|
||||
) : Tier()
|
||||
|
||||
data class Builder(
|
||||
override val id: String,
|
||||
override val isCurrent: Boolean,
|
||||
val price: String = ""
|
||||
) : Tier()
|
||||
|
||||
data class CoCreator(
|
||||
override val id: String,
|
||||
override val isCurrent: Boolean,
|
||||
val price: String = ""
|
||||
) : Tier()
|
||||
|
||||
data class Custom(
|
||||
override val id: String,
|
||||
override val isCurrent: Boolean,
|
||||
val price: String = ""
|
||||
) : Tier()
|
||||
}
|
|
@ -16,7 +16,6 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
@ -33,8 +32,6 @@ fun InfoCard(
|
|||
title: String,
|
||||
subtitle: String,
|
||||
) {
|
||||
val configuration = LocalConfiguration.current
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.height(284.dp)
|
||||
|
|
|
@ -53,8 +53,8 @@ import com.anytypeio.anytype.core_ui.views.BodyRegular
|
|||
import com.anytypeio.anytype.core_ui.views.Caption1Regular
|
||||
import com.anytypeio.anytype.core_ui.views.Relations2
|
||||
import com.anytypeio.anytype.core_ui.views.fontRiccioneRegular
|
||||
import com.anytypeio.anytype.models.Tier
|
||||
import com.anytypeio.anytype.viewmodel.PaymentsState
|
||||
import com.anytypeio.anytype.viewmodel.TierState
|
||||
|
||||
@Composable
|
||||
fun MainPaymentsScreen(state: PaymentsState) {
|
||||
|
@ -78,7 +78,7 @@ fun MainPaymentsScreen(state: PaymentsState) {
|
|||
Header(state = state)
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
InfoCards()
|
||||
Tiers(state = state)
|
||||
TiersList(state = state)
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
LinkButton(text = stringResource(id = R.string.payments_member_link), action = {})
|
||||
Divider()
|
||||
|
@ -90,6 +90,7 @@ fun MainPaymentsScreen(state: PaymentsState) {
|
|||
}
|
||||
}
|
||||
}
|
||||
MembershipLevels(tier = Tier.Explorer(id = "888", isCurrent = true))
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
@ -140,7 +141,7 @@ private fun Header(state: PaymentsState.Success) {
|
|||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun Tiers(state: PaymentsState.Success) {
|
||||
fun TiersList(state: PaymentsState.Success) {
|
||||
val itemsScroll = rememberLazyListState(initialFirstVisibleItemIndex = 1)
|
||||
LazyRow(
|
||||
state = itemsScroll,
|
||||
|
@ -151,8 +152,17 @@ fun Tiers(state: PaymentsState.Success) {
|
|||
contentPadding = PaddingValues(start = 20.dp, end = 20.dp),
|
||||
flingBehavior = rememberSnapFlingBehavior(lazyListState = itemsScroll)
|
||||
) {
|
||||
itemsIndexed(state.tiers) { index, tier ->
|
||||
TierByType(tier = tier)
|
||||
itemsIndexed(state.tiers) { _, tier ->
|
||||
val resources = mapTierToResources(tier)
|
||||
TierView(
|
||||
title = resources.title,
|
||||
subTitle = resources.subtitle,
|
||||
colorGradient = resources.colorGradient,
|
||||
radialGradient = resources.radialGradient,
|
||||
icon = resources.smallIcon,
|
||||
buttonText = stringResource(id = R.string.payments_button_learn),
|
||||
onClick = { /*TODO*/ }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,10 +267,10 @@ fun BottomText() {
|
|||
@Composable
|
||||
fun MainPaymentsScreenPreview() {
|
||||
val tiers = listOf(
|
||||
TierState.Explorer("999", isCurrent = true),
|
||||
TierState.Builder("999", isCurrent = false),
|
||||
TierState.CoCreator("999", isCurrent = false),
|
||||
TierState.Custom("999", isCurrent = false)
|
||||
Tier.Explorer("999", isCurrent = true),
|
||||
Tier.Builder("999", isCurrent = false),
|
||||
Tier.CoCreator("999", isCurrent = false),
|
||||
Tier.Custom("999", isCurrent = false)
|
||||
)
|
||||
MainPaymentsScreen(PaymentsState.Success(tiers))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,226 @@
|
|||
package com.anytypeio.anytype.screens
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.FractionalThreshold
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.rememberSwipeableState
|
||||
import androidx.compose.material.swipeable
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleThrottledClickable
|
||||
import com.anytypeio.anytype.core_ui.views.BodyBold
|
||||
import com.anytypeio.anytype.core_ui.views.BodyCallout
|
||||
import com.anytypeio.anytype.core_ui.views.BodyRegular
|
||||
import com.anytypeio.anytype.core_ui.views.Caption1Regular
|
||||
import com.anytypeio.anytype.core_ui.views.HeadlineTitle
|
||||
import com.anytypeio.anytype.core_ui.widgets.DragStates
|
||||
import com.anytypeio.anytype.models.Tier
|
||||
import com.anytypeio.anytype.peyments.R
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun MembershipLevels(tier: Tier) {
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
val focusManager = LocalFocusManager.current
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.background(color = colorResource(id = R.color.shape_tertiary)),
|
||||
contentAlignment = Alignment.BottomStart,
|
||||
) {
|
||||
|
||||
val swipeableState = rememberSwipeableState(DragStates.VISIBLE)
|
||||
val keyboardController = LocalSoftwareKeyboardController.current
|
||||
|
||||
if (swipeableState.isAnimationRunning && swipeableState.targetValue == DragStates.DISMISSED) {
|
||||
DisposableEffect(Unit) {
|
||||
onDispose {
|
||||
keyboardController?.hide()
|
||||
focusManager.clearFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val sizePx =
|
||||
with(LocalDensity.current) { LocalConfiguration.current.screenHeightDp.dp.toPx() }
|
||||
|
||||
val tierResources = mapTierToResources(tier)
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = true,
|
||||
enter = slideInVertically { it },
|
||||
exit = slideOutVertically { it },
|
||||
modifier = Modifier
|
||||
.swipeable(state = swipeableState,
|
||||
orientation = Orientation.Vertical,
|
||||
anchors = mapOf(
|
||||
0f to DragStates.VISIBLE, sizePx to DragStates.DISMISSED
|
||||
),
|
||||
thresholds = { _, _ -> FractionalThreshold(0.3f) })
|
||||
.offset { IntOffset(0, swipeableState.offset.value.roundToInt()) }
|
||||
) {
|
||||
val brush = Brush.verticalGradient(
|
||||
listOf(
|
||||
tierResources.colorGradient,
|
||||
Color.Transparent
|
||||
)
|
||||
)
|
||||
|
||||
Column {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(132.dp)
|
||||
.background(brush = brush, shape = RoundedCornerShape(16.dp)),
|
||||
contentAlignment = androidx.compose.ui.Alignment.BottomStart
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.padding(start = 16.dp),
|
||||
painter = painterResource(id = tierResources.mediumIcon!!),
|
||||
contentDescription = "logo",
|
||||
tint = tierResources.radialGradient
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(14.dp))
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp),
|
||||
text = tierResources.title,
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
style = HeadlineTitle,
|
||||
textAlign = TextAlign.Start
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 20.dp, end = 20.dp, top = 6.dp),
|
||||
text = tierResources.subtitle,
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
style = BodyCallout,
|
||||
textAlign = TextAlign.Start
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 20.dp, end = 20.dp, top = 22.dp),
|
||||
text = stringResource(id = R.string.payments_details_whats_included),
|
||||
color = colorResource(id = R.color.text_secondary),
|
||||
style = BodyCallout,
|
||||
textAlign = TextAlign.Start
|
||||
)
|
||||
Spacer(modifier = Modifier.height(6.dp))
|
||||
tierResources.benefits.forEach { benefit ->
|
||||
Benefit(benefit = benefit)
|
||||
Spacer(modifier = Modifier.height(6.dp))
|
||||
}
|
||||
Spacer(modifier = Modifier.height(30.dp))
|
||||
NamePicker()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun NamePicker() {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.background(
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
color = colorResource(id = R.color.background_primary)
|
||||
)
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 20.dp, end = 20.dp, top = 26.dp),
|
||||
text = stringResource(id = R.string.payments_details_name_title),
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
style = BodyBold,
|
||||
textAlign = TextAlign.Start
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 20.dp, end = 20.dp, top = 6.dp),
|
||||
text = stringResource(id = R.string.payments_details_name_subtitle),
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
style = BodyCallout,
|
||||
textAlign = TextAlign.Start
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Benefit(benefit: String) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.wrapContentHeight()
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp)
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.wrapContentSize()
|
||||
.align(Alignment.CenterStart),
|
||||
painter = painterResource(id = R.drawable.ic_check_16),
|
||||
contentDescription = "text check icon"
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 22.dp)
|
||||
.align(Alignment.CenterStart),
|
||||
text = benefit,
|
||||
style = BodyCallout,
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Preview()
|
||||
@Composable
|
||||
fun MyLevel() {
|
||||
MembershipLevels(tier = Tier.Explorer("121", true))
|
||||
}
|
|
@ -18,6 +18,7 @@ import androidx.compose.ui.graphics.Brush
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringArrayResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
|
@ -32,13 +33,12 @@ import com.anytypeio.anytype.core_ui.views.ButtonPrimary
|
|||
import com.anytypeio.anytype.core_ui.views.ButtonSize
|
||||
import com.anytypeio.anytype.core_ui.views.Caption1Regular
|
||||
import com.anytypeio.anytype.core_ui.views.fontInterSemibold
|
||||
import com.anytypeio.anytype.viewmodel.TierState
|
||||
import com.anytypeio.anytype.models.Tier
|
||||
|
||||
@Composable
|
||||
private fun Tier(
|
||||
fun TierView(
|
||||
title: String,
|
||||
subTitle: String,
|
||||
price: String,
|
||||
colorGradient: Color,
|
||||
radialGradient: Color,
|
||||
icon: Int,
|
||||
|
@ -120,72 +120,58 @@ fun PriceOrOption() {
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun TierByType(tier: TierState) {
|
||||
when (tier) {
|
||||
is TierState.Builder -> {
|
||||
Tier(
|
||||
title = stringResource(id = R.string.payments_tier_builder),
|
||||
subTitle = stringResource(id = R.string.payments_tier_builder_description),
|
||||
price = tier.price,
|
||||
colorGradient = Color(0xFFE4E7FF),
|
||||
radialGradient = Color(0xFFA5AEFF),
|
||||
icon = R.drawable.logo_builder,
|
||||
buttonText = stringResource(id = R.string.payments_button_learn),
|
||||
onClick = { /*TODO*/ }
|
||||
)
|
||||
}
|
||||
fun mapTierToResources(tier: Tier): TierResources {
|
||||
return when (tier) {
|
||||
is Tier.Builder -> TierResources(
|
||||
title = stringResource(id = R.string.payments_tier_builder),
|
||||
subtitle = stringResource(id = R.string.payments_tier_builder_description),
|
||||
mediumIcon = R.drawable.logo_builder_96,
|
||||
smallIcon = R.drawable.logo_builder_64,
|
||||
colorGradient = Color(0xFFE4E7FF),
|
||||
radialGradient = Color(0xFFA5AEFF),
|
||||
benefits = stringArrayResource(id = R.array.payments_benefits_builder).toList()
|
||||
)
|
||||
|
||||
is TierState.CoCreator -> {
|
||||
Tier(
|
||||
title = stringResource(id = R.string.payments_tier_cocreator),
|
||||
subTitle = stringResource(id = R.string.payments_tier_cocreator_description),
|
||||
price = tier.price,
|
||||
colorGradient = Color(0xFFFBEAEA),
|
||||
radialGradient = Color(0xFFF05F5F),
|
||||
icon = R.drawable.logo_co_creator,
|
||||
buttonText = stringResource(id = R.string.payments_button_learn),
|
||||
onClick = { /*TODO*/ }
|
||||
)
|
||||
}
|
||||
is Tier.CoCreator -> TierResources(
|
||||
title = stringResource(id = R.string.payments_tier_cocreator),
|
||||
subtitle = stringResource(id = R.string.payments_tier_cocreator_description),
|
||||
mediumIcon = R.drawable.logo_co_creator_96,
|
||||
smallIcon = R.drawable.logo_co_creator_64,
|
||||
colorGradient = Color(0xFFFBEAEA),
|
||||
radialGradient = Color(0xFFF05F5F),
|
||||
benefits = stringArrayResource(id = R.array.payments_benefits_cocreator).toList()
|
||||
)
|
||||
|
||||
is TierState.Custom -> {
|
||||
Tier(
|
||||
title = stringResource(id = R.string.payments_tier_custom),
|
||||
subTitle = stringResource(id = R.string.payments_tier_custom_description),
|
||||
price = tier.price,
|
||||
colorGradient = Color(0xFFFBEAFF),
|
||||
radialGradient = Color(0xFFFE86DE3),
|
||||
icon = R.drawable.logo_custom,
|
||||
buttonText = stringResource(id = R.string.payments_button_learn),
|
||||
onClick = { /*TODO*/ }
|
||||
)
|
||||
}
|
||||
is Tier.Custom -> TierResources(
|
||||
title = stringResource(id = R.string.payments_tier_custom),
|
||||
subtitle = stringResource(id = R.string.payments_tier_custom_description),
|
||||
smallIcon = R.drawable.logo_custom_64,
|
||||
colorGradient = Color(0xFFFBEAFF),
|
||||
radialGradient = Color(0xFFFE86DE3),
|
||||
benefits = emptyList()
|
||||
)
|
||||
|
||||
is TierState.Explorer -> {
|
||||
Tier(
|
||||
title = stringResource(id = R.string.payments_tier_explorer),
|
||||
subTitle = stringResource(id = R.string.payments_tier_explorer_description),
|
||||
price = tier.price,
|
||||
colorGradient = Color(0xFFCFFAFF),
|
||||
radialGradient = Color(0xFF24BFD4),
|
||||
icon = R.drawable.logo_explorer,
|
||||
buttonText = stringResource(id = R.string.payments_button_learn),
|
||||
onClick = { /*TODO*/ }
|
||||
)
|
||||
}
|
||||
is Tier.Explorer -> TierResources(
|
||||
title = stringResource(id = R.string.payments_tier_explorer),
|
||||
subtitle = stringResource(id = R.string.payments_tier_explorer_description),
|
||||
mediumIcon = R.drawable.logo_explorer_96,
|
||||
smallIcon = R.drawable.logo_explorer_64,
|
||||
colorGradient = Color(0xFFCFFAFF),
|
||||
radialGradient = Color(0xFF24BFD4),
|
||||
benefits = stringArrayResource(id = R.array.payments_benefits_explorer).toList()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun TierPreview() {
|
||||
Tier(
|
||||
TierView(
|
||||
title = "Explorer",
|
||||
subTitle = "Dive into the network and enjoy the thrill of one-on-one collaboration",
|
||||
price = "9.99",
|
||||
buttonText = "Subscribe",
|
||||
onClick = {},
|
||||
icon = R.drawable.logo_co_creator,
|
||||
icon = R.drawable.logo_co_creator_64,
|
||||
colorGradient = Color(0xFFCFF6CF),
|
||||
radialGradient = Color(0xFF24BFD4)
|
||||
)
|
||||
|
@ -197,4 +183,14 @@ val titleTextStyle = TextStyle(
|
|||
fontSize = 17.sp,
|
||||
lineHeight = 24.sp,
|
||||
letterSpacing = (-0.024).em
|
||||
)
|
||||
|
||||
data class TierResources(
|
||||
val title: String,
|
||||
val subtitle: String,
|
||||
val mediumIcon: Int? = null,
|
||||
val smallIcon: Int,
|
||||
val colorGradient: Color,
|
||||
val radialGradient: Color,
|
||||
val benefits: List<String>
|
||||
)
|
|
@ -1,30 +1,8 @@
|
|||
package com.anytypeio.anytype.viewmodel
|
||||
|
||||
import com.anytypeio.anytype.models.Tier
|
||||
|
||||
sealed class PaymentsState {
|
||||
object Loading : PaymentsState()
|
||||
data class Success(val tiers: List<TierState>) : PaymentsState()
|
||||
}
|
||||
|
||||
sealed class TierState {
|
||||
abstract val isCurrent: Boolean
|
||||
|
||||
data class Explorer(
|
||||
val price: String,
|
||||
override val isCurrent: Boolean
|
||||
) : TierState()
|
||||
|
||||
data class Builder(
|
||||
val price: String,
|
||||
override val isCurrent: Boolean
|
||||
) : TierState()
|
||||
|
||||
data class CoCreator(
|
||||
val price: String,
|
||||
override val isCurrent: Boolean
|
||||
) : TierState()
|
||||
|
||||
data class Custom(
|
||||
val price: String,
|
||||
override val isCurrent: Boolean
|
||||
) : TierState()
|
||||
data class Success(val tiers: List<Tier>) : PaymentsState()
|
||||
}
|
|
@ -2,6 +2,7 @@ package com.anytypeio.anytype.viewmodel
|
|||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.models.Tier
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import timber.log.Timber
|
||||
|
||||
|
@ -15,10 +16,10 @@ class PaymentsViewModel(
|
|||
Timber.d("PaymentsViewModel created")
|
||||
viewState.value = PaymentsState.Success(
|
||||
listOf(
|
||||
TierState.Explorer("Free", true),
|
||||
TierState.Builder("$9.99/mo", false),
|
||||
TierState.CoCreator("$19.99/mo", false),
|
||||
TierState.Custom("$29.99/mo", false)
|
||||
Tier.Explorer("Free", true),
|
||||
Tier.Builder("$9.99/mo", false),
|
||||
Tier.CoCreator("$19.99/mo", false),
|
||||
Tier.Custom("$29.99/mo", false)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue