improved extra features purchase flow

This commit is contained in:
Mariotaku Lee 2017-03-28 11:15:58 +08:00
parent d58337ab79
commit 3d219368cd
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
13 changed files with 65 additions and 52 deletions

View File

@ -1 +1 @@
2cf5b4a092585e624e14f0bb0d7eaff6d0f338bb
e2cd7e2688f9099318c7bf4653c15eb1e7c212cf

View File

@ -493,6 +493,10 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
val df = RetweetProtectedStatusWarnFragment()
df.show(supportFragmentManager,
"retweet_protected_status_warning_message")
} else if (scheduleInfo != null && !extraFeaturesService.isEnabled(ExtraFeaturesService.FEATURE_SCHEDULE_STATUS)) {
ExtraFeaturesIntroductionDialogFragment.show(supportFragmentManager,
feature = ExtraFeaturesService.FEATURE_SCHEDULE_STATUS,
requestCode = REQUEST_PURCHASE_EXTRA_FEATURES)
} else {
updateStatus()
}
@ -549,13 +553,7 @@ class ComposeActivity : BaseActivity(), OnMenuItemClickListener, OnClickListener
}
R.id.schedule -> {
val controller = statusScheduleController ?: return true
if (extraFeaturesService.isEnabled(ExtraFeaturesService.FEATURE_SCHEDULE_STATUS)) {
startActivityForResult(controller.createSetScheduleIntent(), REQUEST_SET_SCHEDULE)
} else {
ExtraFeaturesIntroductionDialogFragment.show(supportFragmentManager,
feature = ExtraFeaturesService.FEATURE_SCHEDULE_STATUS,
requestCode = REQUEST_PURCHASE_EXTRA_FEATURES)
}
startActivityForResult(controller.createSetScheduleIntent(), REQUEST_SET_SCHEDULE)
}
else -> {
val intent = item.intent

View File

@ -47,7 +47,7 @@ class SelectableUsersAdapter(
private val inflater: LayoutInflater = LayoutInflater.from(context)
private val checkedState: MutableMap<UserKey, Boolean> = ArrayMap()
private val lockedState: MutableMap<UserKey, Boolean> = ArrayMap()
var itemCheckedListener: ((Int, Boolean) -> Unit)? = null
var itemCheckedListener: ((Int, Boolean) -> Boolean)? = null
var data: List<ParcelableUser>? = null
set(value) {
@ -174,7 +174,10 @@ class SelectableUsersAdapter(
fun setItemChecked(position: Int, value: Boolean) {
val userKey = getUserKey(position)
setCheckState(userKey, value)
itemCheckedListener?.invoke(position, value)
if (!(itemCheckedListener?.invoke(position, value) ?: true)) {
setCheckState(userKey, !value)
notifyItemChanged(position)
}
}
fun clearCheckState() {

View File

@ -135,14 +135,8 @@ class DraftsFragment : BaseFragment(), LoaderCallbacks<Cursor?>, OnItemClickList
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.scheduled_statuses -> {
if (extraFeaturesService.isEnabled(ExtraFeaturesService.FEATURE_SCHEDULE_STATUS)) {
val scheduleManageIntent = statusScheduleController?.createManageIntent()
startActivity(scheduleManageIntent)
} else {
ExtraFeaturesIntroductionDialogFragment.show(childFragmentManager,
ExtraFeaturesService.FEATURE_SCHEDULE_STATUS,
requestCode = REQUEST_PURCHASE_EXTRA_FEATURES)
}
val scheduleManageIntent = statusScheduleController?.createManageIntent() ?: return true
startActivity(scheduleManageIntent)
return true
}
}

View File

@ -1,10 +1,11 @@
package org.mariotaku.twidere.fragment.filter
import android.app.Activity
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import android.support.v4.app.DialogFragment
import android.support.v4.app.LoaderManager
import android.support.v4.content.Loader
import android.support.v7.app.AlertDialog
@ -20,6 +21,7 @@ import nl.komponents.kovenant.task
import nl.komponents.kovenant.ui.alwaysUi
import org.mariotaku.ktextension.*
import org.mariotaku.twidere.R
import org.mariotaku.twidere.TwidereConstants.REQUEST_PURCHASE_EXTRA_FEATURES
import org.mariotaku.twidere.activity.BaseActivity
import org.mariotaku.twidere.adapter.SelectableUsersAdapter
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter
@ -27,14 +29,14 @@ import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosi
import org.mariotaku.twidere.constant.IntentConstants
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_COUNT
import org.mariotaku.twidere.extension.applyTheme
import org.mariotaku.twidere.fragment.AbsContentListRecyclerViewFragment
import org.mariotaku.twidere.fragment.BaseDialogFragment
import org.mariotaku.twidere.fragment.MessageDialogFragment
import org.mariotaku.twidere.fragment.ProgressDialogFragment
import org.mariotaku.twidere.fragment.*
import org.mariotaku.twidere.loader.CursorSupportUsersLoader
import org.mariotaku.twidere.loader.iface.IExtendedLoader
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.analyzer.PurchaseFinished
import org.mariotaku.twidere.util.Analyzer
import org.mariotaku.twidere.util.DataStoreUtils
import org.mariotaku.twidere.util.premium.ExtraFeaturesService
import java.lang.ref.WeakReference
/**
@ -59,6 +61,16 @@ abstract class BaseFiltersImportFragment : AbsContentListRecyclerViewFragment<Se
loaderManager.initLoader(0, loaderArgs, this)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
REQUEST_PURCHASE_EXTRA_FEATURES -> {
if (resultCode == Activity.RESULT_OK) {
Analyzer.log(PurchaseFinished.create(data!!))
}
}
}
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.menu_filters_import, menu)
}
@ -68,7 +80,7 @@ abstract class BaseFiltersImportFragment : AbsContentListRecyclerViewFragment<Se
val userCount = adapter.userCount
menu.setItemAvailability(R.id.select_none, checkedCount > 0)
menu.setItemAvailability(R.id.select_all, checkedCount < userCount)
menu.setItemAvailability(R.id.invert_selection, checkedCount > 0 && checkedCount < userCount)
menu.setItemAvailability(R.id.invert_selection, checkedCount in 1 until userCount)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
@ -94,6 +106,12 @@ abstract class BaseFiltersImportFragment : AbsContentListRecyclerViewFragment<Se
Toast.makeText(context, R.string.message_toast_no_user_selected, Toast.LENGTH_SHORT).show()
return true
}
if (!extraFeaturesService.isEnabled(ExtraFeaturesService.FEATURE_FILTERS_IMPORT)) {
ExtraFeaturesIntroductionDialogFragment.show(fragmentManager,
feature = ExtraFeaturesService.FEATURE_FILTERS_IMPORT,
requestCode = REQUEST_PURCHASE_EXTRA_FEATURES)
return true
}
val df = ImportConfirmDialogFragment()
df.arguments = Bundle {
this[EXTRA_COUNT] = adapter.checkedCount
@ -169,7 +187,13 @@ abstract class BaseFiltersImportFragment : AbsContentListRecyclerViewFragment<Se
override fun onCreateAdapter(context: Context): SelectableUsersAdapter {
val adapter = SelectableUsersAdapter(context, Glide.with(this))
adapter.itemCheckedListener = { _, _ ->
adapter.itemCheckedListener = listener@ { position, value ->
if (!extraFeaturesService.isEnabled(ExtraFeaturesService.FEATURE_FILTERS_IMPORT)) {
ExtraFeaturesIntroductionDialogFragment.show(fragmentManager,
feature = ExtraFeaturesService.FEATURE_FILTERS_IMPORT,
requestCode = REQUEST_PURCHASE_EXTRA_FEATURES)
return@listener false
}
val count = adapter.checkedCount
val actionBar = (activity as BaseActivity).supportActionBar
actionBar?.subtitle = if (count > 0) {
@ -178,6 +202,7 @@ abstract class BaseFiltersImportFragment : AbsContentListRecyclerViewFragment<Se
null
}
activity.supportInvalidateOptionsMenu()
return@listener true
}
return adapter
}

View File

@ -1,14 +1,12 @@
package org.mariotaku.twidere.fragment.filter
import android.net.Uri
import org.mariotaku.twidere.provider.TwidereDataStore
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
class FilteredKeywordsFragment : BaseFiltersFragment() {
override val contentUri: Uri
get() = TwidereDataStore.Filters.Keywords.CONTENT_URI
override val contentUri: Uri = Filters.Keywords.CONTENT_URI
override val contentColumns: Array<String>
get() = TwidereDataStore.Filters.Keywords.COLUMNS
override val contentColumns: Array<String> = Filters.Keywords.COLUMNS
}

View File

@ -1,15 +1,12 @@
package org.mariotaku.twidere.fragment.filter
import android.net.Uri
import org.mariotaku.twidere.fragment.filter.BaseFiltersFragment
import org.mariotaku.twidere.provider.TwidereDataStore
import org.mariotaku.twidere.provider.TwidereDataStore.Filters
class FilteredLinksFragment : BaseFiltersFragment() {
override val contentColumns: Array<String>
get() = TwidereDataStore.Filters.Links.COLUMNS
override val contentColumns: Array<String> = Filters.Links.COLUMNS
override val contentUri: Uri
get() = TwidereDataStore.Filters.Links.CONTENT_URI
override val contentUri: Uri = Filters.Links.CONTENT_URI
}

View File

@ -29,7 +29,6 @@ import org.mariotaku.twidere.activity.UserSelectorActivity
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_ACCOUNT_HOST
import org.mariotaku.twidere.constant.nameFirstKey
import org.mariotaku.twidere.fragment.AddUserFilterDialogFragment
import org.mariotaku.twidere.fragment.ExtraFeaturesIntroductionDialogFragment
import org.mariotaku.twidere.model.FiltersData
import org.mariotaku.twidere.model.ParcelableUser
import org.mariotaku.twidere.model.UserKey
@ -41,7 +40,6 @@ import org.mariotaku.twidere.util.ThemeUtils
import org.mariotaku.twidere.util.UserColorNameManager
import org.mariotaku.twidere.util.content.ContentResolverUtils
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import org.mariotaku.twidere.util.premium.ExtraFeaturesService
import javax.inject.Inject
class FilteredUsersFragment : BaseFiltersFragment() {
@ -105,31 +103,22 @@ class FilteredUsersFragment : BaseFiltersFragment() {
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
var isExtraFeatures: Boolean = false
val intent = Intent(context, AccountSelectorActivity::class.java)
intent.putExtra(EXTRA_SINGLE_SELECTION, true)
intent.putExtra(EXTRA_SELECT_ONLY_ITEM_AUTOMATICALLY, true)
val requestCode = when (item.itemId) {
R.id.add_user_single, R.id.add_user -> REQUEST_ADD_USER_SELECT_ACCOUNT
R.id.import_from_blocked_users -> {
isExtraFeatures = true
REQUEST_IMPORT_BLOCKS_SELECT_ACCOUNT
}
R.id.import_from_muted_users -> {
isExtraFeatures = true
intent.putExtra(EXTRA_ACCOUNT_HOST, USER_TYPE_TWITTER_COM)
REQUEST_IMPORT_MUTES_SELECT_ACCOUNT
}
else -> return false
}
if (!isExtraFeatures || extraFeaturesService.isEnabled(ExtraFeaturesService.FEATURE_FILTERS_IMPORT)) {
startActivityForResult(intent, requestCode)
} else {
ExtraFeaturesIntroductionDialogFragment.show(childFragmentManager,
feature = ExtraFeaturesService.FEATURE_FILTERS_IMPORT,
requestCode = REQUEST_PURCHASE_EXTRA_FEATURES)
}
startActivityForResult(intent, requestCode)
return true
}

View File

@ -140,8 +140,8 @@ class MessageNewConversationFragment : BaseFragment(), LoaderCallbacks<List<Parc
val roundRadius = resources.getDimension(R.dimen.element_spacing_xsmall)
val spanPadding = resources.getDimension(R.dimen.element_spacing_xsmall)
usersAdapter.itemCheckedListener = itemChecked@ { pos, checked ->
val text: Editable = editParticipants.editableText ?: return@itemChecked
val user = usersAdapter.getUser(pos) ?: return@itemChecked
val text: Editable = editParticipants.editableText ?: return@itemChecked false
val user = usersAdapter.getUser(pos) ?: return@itemChecked false
if (checked) {
text.getSpans(0, text.length, PendingQuerySpan::class.java).forEach { pending ->
val start = text.getSpanStart(pending)
@ -173,6 +173,7 @@ class MessageNewConversationFragment : BaseFragment(), LoaderCallbacks<List<Parc
}
editParticipants.clearComposingText()
updateCheckState()
return@itemChecked true
}
}

View File

@ -7,6 +7,7 @@ import org.mariotaku.kpreferences.KPreferences
import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper
import org.mariotaku.twidere.util.media.MediaPreloader
import org.mariotaku.twidere.util.premium.ExtraFeaturesService
import org.mariotaku.twidere.util.schedule.StatusScheduleController
import javax.inject.Inject
@ -35,6 +36,8 @@ abstract class BaseAbstractTask<Params, Result, Callback>(val context: Context)
@Inject
lateinit var userColorNameManager: UserColorNameManager
@Inject
lateinit var extraFeaturesService: ExtraFeaturesService
@Inject
lateinit var scheduleControllerFactory: StatusScheduleController.Factory
val scheduleController: StatusScheduleController?

View File

@ -51,6 +51,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Drafts
import org.mariotaku.twidere.task.BaseAbstractTask
import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.io.ContentLengthInputStream
import org.mariotaku.twidere.util.premium.ExtraFeaturesService
import java.io.Closeable
import java.io.File
import java.io.FileNotFoundException
@ -257,9 +258,12 @@ class UpdateStatusTask(
): UpdateStatusResult {
stateCallback.onUpdatingStatus()
if (!extraFeaturesService.isEnabled(ExtraFeaturesService.FEATURE_SCHEDULE_STATUS)) {
throw SchedulerNotFoundException(context.getString(R.string.error_message_scheduler_not_available))
}
val controller = scheduleController ?: run {
throw SchedulerNotFoundException("No scheduler found")
throw SchedulerNotFoundException(context.getString(R.string.error_message_scheduler_not_available))
}
controller.scheduleStatus(statusUpdate, pendingUpdate, scheduleInfo)

View File

@ -51,7 +51,6 @@ abstract class ExtraFeaturesService {
const val FEATURE_FILTERS_IMPORT = "import_filters"
const val FEATURE_FILTERS_SUBSCRIPTION = "filters_subscriptions"
const val FEATURE_SYNC_DATA = "sync_data"
const val FEATURE_SCHEDULE_STATUS = "schedule_status"
fun newInstance(context: Context): ExtraFeaturesService {

View File

@ -368,6 +368,7 @@
<string name="error_message_no_content">No content</string>
<string name="error_message_rate_limit">Twitter\'s rate limit exceeded, please retry <xliff:g id="time">%s</xliff:g></string>
<string name="error_message_rate_limit_with_action">Twitter\'s rate limit exceeded while <xliff:g id="action">%1$s</xliff:g>, please retry <xliff:g id="time">%2$s</xliff:g></string>
<string name="error_message_scheduler_not_available">Tweet schedule not available</string>
<string name="error_message_status_too_long">Tweet too long.</string>
<string name="error_message_tweet_shorten_failed">Tweet shorten failed.</string>
<string name="error_message_tweet_shortener_not_found">Tweet shortener not found, maybe it was uninstalled.</string>
@ -599,6 +600,7 @@
<string name="message_auto_refresh_confirm">Enable auto refresh to get new tweets automatically?</string>
<string name="message_blocked_user">Blocked <xliff:g id="user">%s</xliff:g>.</string>
<string name="message_buffer_delete_schedule_confirm">Delete this schedule?</string>
<string name="message_buffer_disconnect_confirm">Disconnect from Buffer?</string>
<string name="message_clear_messages_confirm">Clear all messages?</string>
<string name="message_conversation_created">Conversation created.</string>
<string name="message_destroy_conversation_confirm">Leave this conversation?</string>