mirror of
https://github.com/anyproto/anytype-kotlin.git
synced 2025-06-08 05:47:05 +09:00
DROID-2722 Membership | Open tier deeplink (#1493)
This commit is contained in:
parent
3104a623c0
commit
e7a37b4299
9 changed files with 95 additions and 2 deletions
|
@ -66,6 +66,13 @@
|
|||
<data android:scheme="anytype" />
|
||||
<data android:host="object" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="anytype" />
|
||||
<data android:host="membership" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
|
|
@ -20,12 +20,14 @@ const val MAIN_PATH = "main"
|
|||
const val OBJECT_PATH = "object"
|
||||
const val IMPORT_PATH = "import"
|
||||
const val INVITE_PATH = "invite"
|
||||
const val MEMBERSHIP_PATH = "membership"
|
||||
|
||||
const val TYPE_PARAM = "type"
|
||||
const val OBJECT_ID_PARAM = "objectId"
|
||||
const val SPACE_ID_PARAM = "spaceId"
|
||||
const val SOURCE_PARAM = "source"
|
||||
const val TYPE_VALUE_EXPERIENCE = "experience"
|
||||
const val TIER_ID_PARAM = "tier"
|
||||
|
||||
const val IMPORT_EXPERIENCE_DEEPLINK = "$DEEP_LINK_PATTERN$MAIN_PATH/$IMPORT_PATH/?$TYPE_PARAM=$TYPE_VALUE_EXPERIENCE"
|
||||
|
||||
|
@ -67,6 +69,12 @@ object DefaultDeepLinkResolver : DeepLinkResolver {
|
|||
DeepLinkResolver.Action.Unknown
|
||||
}
|
||||
}
|
||||
deeplink.contains(MEMBERSHIP_PATH) -> {
|
||||
val uri = Uri.parse(deeplink)
|
||||
DeepLinkResolver.Action.DeepLinkToMembership(
|
||||
tierId = uri.getQueryParameter(TIER_ID_PARAM)
|
||||
)
|
||||
}
|
||||
else -> DeepLinkResolver.Action.Unknown
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import androidx.fragment.app.viewModels
|
|||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.navigation.NavOptions
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
|
@ -36,6 +37,7 @@ import com.anytypeio.anytype.ui.gallery.GalleryInstallationFragment
|
|||
import com.anytypeio.anytype.ui.multiplayer.RequestJoinSpaceFragment
|
||||
import com.anytypeio.anytype.ui.multiplayer.ShareSpaceFragment
|
||||
import com.anytypeio.anytype.ui.objects.creation.SelectObjectTypeFragment
|
||||
import com.anytypeio.anytype.ui.payments.MembershipFragment
|
||||
import com.anytypeio.anytype.ui.settings.space.SpaceSettingsFragment
|
||||
import com.anytypeio.anytype.ui.settings.typography
|
||||
import com.anytypeio.anytype.ui.widgets.SelectWidgetSourceFragment
|
||||
|
@ -245,6 +247,13 @@ class HomeScreenFragment : BaseComposeFragment() {
|
|||
)
|
||||
)
|
||||
}
|
||||
is Command.Deeplink.MembershipScreen -> {
|
||||
findNavController().navigate(
|
||||
R.id.paymentsScreen,
|
||||
MembershipFragment.args(command.tierId),
|
||||
NavOptions.Builder().setLaunchSingleTop(true).build()
|
||||
)
|
||||
}
|
||||
is Command.Deeplink.DeepLinkToObjectNotWorking -> {
|
||||
toast(
|
||||
getString(R.string.multiplayer_deeplink_to_your_object_error)
|
||||
|
|
|
@ -55,6 +55,7 @@ import com.anytypeio.anytype.ui.multiplayer.RequestJoinSpaceFragment
|
|||
import com.anytypeio.anytype.ui.multiplayer.ShareSpaceFragment
|
||||
import com.anytypeio.anytype.ui.multiplayer.SpaceJoinRequestFragment
|
||||
import com.anytypeio.anytype.ui.notifications.NotificationsFragment
|
||||
import com.anytypeio.anytype.ui.payments.MembershipFragment
|
||||
import com.anytypeio.anytype.ui.sets.ObjectSetFragment
|
||||
import com.anytypeio.anytype.ui.sharing.SharingFragment
|
||||
import com.anytypeio.anytype.ui_settings.appearance.ThemeApplicator
|
||||
|
@ -251,6 +252,17 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), AppNavigation.Pr
|
|||
Timber.e(it, "Error while navigation for deep link invite")
|
||||
}
|
||||
}
|
||||
is Command.Deeplink.MembershipScreen -> {
|
||||
runCatching {
|
||||
findNavController(R.id.fragment).navigate(
|
||||
R.id.paymentsScreen,
|
||||
MembershipFragment.args(tierId = command.tierId),
|
||||
NavOptions.Builder().setLaunchSingleTop(true).build()
|
||||
)
|
||||
}.onFailure {
|
||||
Timber.w(it, "Error while navigation for deep link membership tier")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
|
@ -23,6 +24,7 @@ import com.anytypeio.anytype.BuildConfig
|
|||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_ui.common.ComposeDialogView
|
||||
import com.anytypeio.anytype.core_ui.views.BaseTwoButtonsDarkThemeAlertDialog
|
||||
import com.anytypeio.anytype.core_utils.ext.argOrNull
|
||||
import com.anytypeio.anytype.core_utils.ext.setupBottomSheetBehavior
|
||||
import com.anytypeio.anytype.core_utils.ext.subscribe
|
||||
import com.anytypeio.anytype.core_utils.ext.toast
|
||||
|
@ -59,6 +61,8 @@ class MembershipFragment : BaseBottomSheetComposeFragment() {
|
|||
private val vm by viewModels<MembershipViewModel> { factory }
|
||||
private lateinit var navController: NavHostController
|
||||
|
||||
private val argTierId get() = argOrNull<String>(ARG_TIER_ID)
|
||||
|
||||
@Inject
|
||||
lateinit var billingClientLifecycle: BillingClientLifecycle
|
||||
|
||||
|
@ -183,6 +187,7 @@ class MembershipFragment : BaseBottomSheetComposeFragment() {
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
vm.showTierOnStart(tierId = argTierId)
|
||||
setupBottomSheetBehavior(DEFAULT_PADDING_TOP)
|
||||
subscribe(vm.navigation) { command ->
|
||||
Timber.d("MembershipFragment command: $command")
|
||||
|
@ -209,10 +214,12 @@ class MembershipFragment : BaseBottomSheetComposeFragment() {
|
|||
toast("Couldn't parse url: ${command.url}")
|
||||
}
|
||||
}
|
||||
|
||||
MembershipNavigation.Main -> {}
|
||||
is MembershipNavigation.OpenEmail -> {
|
||||
val mail = resources.getString(R.string.payments_email_to)
|
||||
val subject = resources.getString(R.string.payments_email_subject, command.accountId)
|
||||
val subject =
|
||||
resources.getString(R.string.payments_email_subject, command.accountId)
|
||||
val body = resources.getString(R.string.payments_email_body)
|
||||
val mailBody = mail +
|
||||
"?subject=$subject" +
|
||||
|
@ -228,7 +235,8 @@ class MembershipFragment : BaseBottomSheetComposeFragment() {
|
|||
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
||||
currentDateTime = sdf.format(Date())
|
||||
val mail = resources.getString(R.string.membership_support_email)
|
||||
val subject = resources.getString(R.string.membership_support_subject, command.accountId)
|
||||
val subject =
|
||||
resources.getString(R.string.membership_support_subject, command.accountId)
|
||||
val body = getString(
|
||||
R.string.membership_support_body,
|
||||
command.error, currentDateTime, deviceModel, osVersion, appVersion
|
||||
|
@ -260,4 +268,9 @@ class MembershipFragment : BaseBottomSheetComposeFragment() {
|
|||
override fun releaseDependencies() {
|
||||
componentManager().membershipComponent.release()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val ARG_TIER_ID = "args.membership.tier"
|
||||
fun args(tierId: String?) = bundleOf(ARG_TIER_ID to tierId)
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package com.anytypeio.anytype.domain.misc
|
|||
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Url
|
||||
import com.anytypeio.anytype.core_models.membership.TierId
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
|
||||
interface DeepLinkResolver {
|
||||
|
@ -22,5 +23,8 @@ interface DeepLinkResolver {
|
|||
val obj: Id,
|
||||
val space: SpaceId
|
||||
) : Action()
|
||||
data class DeepLinkToMembership(
|
||||
val tierId: String?
|
||||
) : Action()
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ import com.anytypeio.anytype.domain.payments.SetMembershipEmail
|
|||
import com.anytypeio.anytype.domain.payments.VerifyMembershipEmailCode
|
||||
import com.anytypeio.anytype.core_models.membership.MembershipConstants.EXPLORER_ID
|
||||
import com.anytypeio.anytype.core_models.membership.MembershipConstants.MEMBERSHIP_NAME_MIN_LENGTH
|
||||
import com.anytypeio.anytype.core_models.membership.MembershipConstants.NONE_ID
|
||||
import com.anytypeio.anytype.payments.mapping.toMainView
|
||||
import com.anytypeio.anytype.payments.models.MembershipPurchase
|
||||
import com.anytypeio.anytype.payments.models.TierAnyName
|
||||
|
@ -46,6 +47,8 @@ import kotlinx.coroutines.flow.asSharedFlow
|
|||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterIsInstance
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
|
@ -71,6 +74,8 @@ class MembershipViewModel(
|
|||
|
||||
val navigation = MutableSharedFlow<MembershipNavigation>(0)
|
||||
|
||||
private val _showTierOnStart = MutableStateFlow(NONE_ID)
|
||||
|
||||
/**
|
||||
* Local billing purchase data.
|
||||
*/
|
||||
|
@ -93,6 +98,17 @@ class MembershipViewModel(
|
|||
val anyEmailState = TextFieldState(initialText = "")
|
||||
|
||||
init {
|
||||
Timber.i("MembershipViewModel, init")
|
||||
viewModelScope.launch {
|
||||
combine(
|
||||
_showTierOnStart.filter { it != NONE_ID },
|
||||
viewState.filterIsInstance<MembershipMainState.Default>()
|
||||
) { tierId, _ -> tierId }.collect { tierId ->
|
||||
Timber.d("_showTierOnStart, get new value:$tierId")
|
||||
proceedWithShowingTier(TierId(tierId))
|
||||
}
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
val account = getAccount.async(Unit)
|
||||
val accountId = account.getOrNull()?.id.orEmpty()
|
||||
|
@ -131,6 +147,13 @@ class MembershipViewModel(
|
|||
}
|
||||
}
|
||||
|
||||
fun showTierOnStart(tierId: String?) {
|
||||
val tier = tierId?.toIntOrNull()
|
||||
if (tier != null && tier != NONE_ID) {
|
||||
_showTierOnStart.value = tier
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedWithUpdatingVisibleTier(mainState: MembershipMainState) {
|
||||
val actualTier = tierState.value
|
||||
if (actualTier is MembershipTierState.Visible && mainState is MembershipMainState.Default) {
|
||||
|
|
|
@ -1272,6 +1272,15 @@ class HomeScreenViewModel(
|
|||
}
|
||||
}
|
||||
}
|
||||
is DeepLinkResolver.Action.DeepLinkToMembership -> {
|
||||
viewModelScope.launch {
|
||||
commands.emit(
|
||||
Command.Deeplink.MembershipScreen(
|
||||
tierId = deeplink.tierId
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
Timber.d("No deep link")
|
||||
}
|
||||
|
@ -2190,6 +2199,7 @@ sealed class Command {
|
|||
val deepLinkType: String,
|
||||
val deepLinkSource: String
|
||||
) : Deeplink()
|
||||
data class MembershipScreen(val tierId: String?) : Deeplink()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import com.anytypeio.anytype.core_models.NotificationPayload
|
|||
import com.anytypeio.anytype.core_models.NotificationStatus
|
||||
import com.anytypeio.anytype.core_models.Wallpaper
|
||||
import com.anytypeio.anytype.core_models.exceptions.NeedToUpdateApplicationException
|
||||
import com.anytypeio.anytype.core_models.membership.TierId
|
||||
import com.anytypeio.anytype.core_utils.ext.cancel
|
||||
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
|
||||
import com.anytypeio.anytype.domain.account.InterceptAccountStatus
|
||||
|
@ -350,6 +351,11 @@ class MainViewModel(
|
|||
}
|
||||
}
|
||||
}
|
||||
is DeepLinkResolver.Action.DeepLinkToMembership -> {
|
||||
commands.emit(
|
||||
Command.Deeplink.MembershipScreen(tierId = deeplink.tierId)
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
Timber.d("No deep link")
|
||||
}
|
||||
|
@ -381,6 +387,7 @@ class MainViewModel(
|
|||
val deepLinkType: String,
|
||||
val deepLinkSource: String
|
||||
) : Deeplink()
|
||||
data class MembershipScreen(val tierId: String?) : Deeplink()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue