-
Notifications
You must be signed in to change notification settings - Fork 109
feat: add verify-mobile reminder and gate wallet buy flow #6079
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
edfc20a
57f457e
be8f47e
adc68fb
36a0311
17757cb
4963651
ff9cc3d
721670b
a2e98cc
b851048
524311e
286779a
e077733
9b848ee
116e9e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,5 +33,6 @@ enum class VerificationPurpose { | |
| SESSION, | ||
| PHONE, | ||
| DEACTIVATED, | ||
| ANONYMOUS_SESSION | ||
| ANONYMOUS_SESSION, | ||
| NONE | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,197 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package one.mixin.android.ui.home.reminder | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.annotation.SuppressLint | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.app.Dialog | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.content.Context | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.view.Gravity | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.view.View | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import android.view.ViewGroup | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import androidx.compose.runtime.Composable | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import dagger.hilt.android.AndroidEntryPoint | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.Constants | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.R | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.compose.theme.MixinAppTheme | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.extension.booleanFromAttribute | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.extension.defaultSharedPreferences | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.extension.getSafeAreaInsetsTop | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.extension.isNightMode | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.extension.navTo | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.extension.putLong | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.extension.screenHeight | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.session.Session | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.ui.common.MixinComposeBottomSheetDialogFragment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.ui.common.VerifyFragment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.ui.setting.AddPhoneBeforeFragment | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.util.SystemUIManager | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import one.mixin.android.vo.Account | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import java.time.Instant | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @AndroidEntryPoint | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class VerifyMobileReminderBottomSheetDialogFragment : MixinComposeBottomSheetDialogFragment() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1
to
+30
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| companion object { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const val TAG: String = "VerifyMobileReminderBottomSheetDialogFragment" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private const val PREF_VERIFY_MOBILE_REMINDER_SNOOZE: String = "pref_verify_mobile_reminder_snooze" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private const val ARGS_SUBTITLE_RES_ID: String = "args_subtitle_res_id" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private const val ARGS_ENABLE_SNOOZE: String = "args_enable_snooze" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @Volatile | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private var isShowing = false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fun newInstance(subtitleResId: Int = R.string.Verify_Mobile_Number_Desc): VerifyMobileReminderBottomSheetDialogFragment? { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (isShowing) return null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return VerifyMobileReminderBottomSheetDialogFragment().apply { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| arguments = android.os.Bundle().apply { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| putInt(ARGS_SUBTITLE_RES_ID, subtitleResId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| putBoolean(ARGS_ENABLE_SNOOZE, true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fun newInstance( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| subtitleResId: Int = R.string.Verify_Mobile_Number_Desc, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| enableSnooze: Boolean, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): VerifyMobileReminderBottomSheetDialogFragment? { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (isShowing) return null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return VerifyMobileReminderBottomSheetDialogFragment().apply { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| arguments = android.os.Bundle().apply { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| putInt(ARGS_SUBTITLE_RES_ID, subtitleResId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| putBoolean(ARGS_ENABLE_SNOOZE, enableSnooze) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fun showSafely( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fragmentManager: androidx.fragment.app.FragmentManager, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| subtitleResId: Int = R.string.Verify_Mobile_Number_Desc, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| enableSnooze: Boolean = true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): Boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (isShowing) return false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val fragment = VerifyMobileReminderBottomSheetDialogFragment().apply { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| arguments = android.os.Bundle().apply { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| putInt(ARGS_SUBTITLE_RES_ID, subtitleResId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| putBoolean(ARGS_ENABLE_SNOOZE, enableSnooze) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fragment.showNow(fragmentManager, TAG) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (e: Exception) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isShowing = false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fun shouldShow(context: Context): Boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val account = Session.getAccount() ?: return false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Session.hasPhone().not()) return false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val lastSnoozeTimeMillis: Long = context.defaultSharedPreferences.getLong(PREF_VERIFY_MOBILE_REMINDER_SNOOZE, 0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (System.currentTimeMillis() - lastSnoozeTimeMillis < Constants.INTERVAL_7_DAYS) return false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return shouldShowWithoutSnooze(account) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fun shouldShowForBuy(context: Context): Boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val account = Session.getAccount() ?: return false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (account.phone.isBlank()) return true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return shouldShowWithoutSnooze(account) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private fun shouldShowWithoutSnooze(account: Account): Boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (account.phone.isBlank()) return true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val phoneVerifiedAt: String? = account.phoneVerifiedAt | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (phoneVerifiedAt.isNullOrBlank()) return true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val verifiedAtMillis: Long = runCatching { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Instant.parse(phoneVerifiedAt).toEpochMilli() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }.getOrNull() ?: return true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return System.currentTimeMillis() - verifiedAtMillis > Constants.INTERVAL_60_DAYS | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+89
to
+111
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fun shouldShow(context: Context): Boolean { | |
| if (!Session.hasPhone()) return false | |
| val account = Session.getAccount() ?: return false | |
| val lastSnoozeTimeMillis: Long = context.defaultSharedPreferences.getLong(PREF_VERIFY_MOBILE_REMINDER_SNOOZE, 0) | |
| if (System.currentTimeMillis() - lastSnoozeTimeMillis < Constants.INTERVAL_7_DAYS) return false | |
| val phoneVerifiedAt: String? = account.phoneVerifiedAt | |
| if (phoneVerifiedAt.isNullOrBlank()) return true | |
| val verifiedAtMillis: Long = runCatching { | |
| Instant.parse(phoneVerifiedAt).toEpochMilli() | |
| }.getOrNull() ?: return true | |
| return System.currentTimeMillis() - verifiedAtMillis > Constants.INTERVAL_60_DAYS | |
| } | |
| private fun isPhoneVerifiedMoreThanSixtyDaysAgo(phoneVerifiedAt: String?): Boolean { | |
| if (phoneVerifiedAt.isNullOrBlank()) return true | |
| val verifiedAtMillis: Long = runCatching { | |
| Instant.parse(phoneVerifiedAt).toEpochMilli() | |
| }.getOrNull() ?: return true | |
| return System.currentTimeMillis() - verifiedAtMillis > Constants.INTERVAL_60_DAYS | |
| } | |
| fun shouldShow(context: Context): Boolean { | |
| if (!Session.hasPhone()) return false | |
| val account = Session.getAccount() ?: return false | |
| val lastSnoozeTimeMillis: Long = context.defaultSharedPreferences.getLong(PREF_VERIFY_MOBILE_REMINDER_SNOOZE, 0) | |
| if (System.currentTimeMillis() - lastSnoozeTimeMillis < Constants.INTERVAL_7_DAYS) return false | |
| return isPhoneVerifiedMoreThanSixtyDaysAgo(account.phoneVerifiedAt) | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file name uses snake_case (verify_mobile_reminder_bottom_sheet_dialog_fragment.kt) instead of PascalCase which is inconsistent with Kotlin naming conventions. The file should be named VerifyMobileReminderBottomSheetDialogFragment.kt to match the class name inside and follow standard Kotlin file naming conventions.