Twidere-App-Android-Twitter.../twidere/src/main/kotlin/org/mariotaku/twidere/activity/PremiumDashboardActivity.kt

287 lines
11 KiB
Kotlin

package org.mariotaku.twidere.activity
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.core.app.NavUtils
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.*
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import com.bumptech.glide.RequestManager
import kotlinx.android.synthetic.main.activity_premium_dashboard.*
import kotlinx.android.synthetic.main.adapter_item_extra_feature_normal.view.*
import nl.komponents.kovenant.combine.and
import nl.komponents.kovenant.task
import nl.komponents.kovenant.ui.alwaysUi
import nl.komponents.kovenant.ui.failUi
import nl.komponents.kovenant.ui.successUi
import org.mariotaku.kpreferences.get
import org.mariotaku.kpreferences.set
import org.mariotaku.ktextension.setItemAvailability
import org.mariotaku.twidere.BuildConfig
import org.mariotaku.twidere.R
import org.mariotaku.twidere.TwidereConstants.REQUEST_PURCHASE_EXTRA_FEATURES
import org.mariotaku.twidere.adapter.BaseRecyclerViewAdapter
import org.mariotaku.twidere.constant.promotionsEnabledKey
import org.mariotaku.twidere.fragment.ProgressDialogFragment
import org.mariotaku.twidere.model.analyzer.PurchaseFinished
import org.mariotaku.twidere.util.Analyzer
import org.mariotaku.twidere.util.dagger.GeneralComponent
import org.mariotaku.twidere.util.premium.ExtraFeaturesService
import org.mariotaku.twidere.util.promotion.PromotionService
import org.mariotaku.twidere.util.schedule.StatusScheduleProvider
import org.mariotaku.twidere.view.ContainerView
import java.lang.ref.WeakReference
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
class PremiumDashboardActivity : BaseActivity() {
private lateinit var adapter: ControllersAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_premium_dashboard)
adapter = ControllersAdapter(this, requestManager)
recyclerView.adapter = adapter
recyclerView.layoutManager = LinearLayoutManager(this)
if (extraFeaturesService.isSupported()) {
adapter.controllers = extraFeaturesService.getDashboardControllers()
} else {
finish()
}
}
override fun onPause() {
super.onPause()
val lm = recyclerView.layoutManager as LinearLayoutManager
for (pos in lm.findFirstVisibleItemPosition()..lm.findLastVisibleItemPosition()) {
val holder = recyclerView.findViewHolderForLayoutPosition(pos) as? ControllerViewHolder ?: return
val controller = holder.controller as? BaseItemViewController ?: return
controller.onPause()
}
}
override fun onResume() {
super.onResume()
val lm = recyclerView.layoutManager as LinearLayoutManager
for (pos in lm.findFirstVisibleItemPosition()..lm.findLastVisibleItemPosition()) {
val holder = recyclerView.findViewHolderForLayoutPosition(pos) as? ControllerViewHolder ?: return
val controller = holder.controller as? BaseItemViewController ?: return
controller.onResume()
}
}
override fun onDestroy() {
extraFeaturesService.release()
if (isFinishing) {
// Make sure promotionsEnabled set
preferences[promotionsEnabledKey] = preferences[promotionsEnabledKey]
}
super.onDestroy()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (resultCode) {
REQUEST_PURCHASE_EXTRA_FEATURES -> {
if (resultCode == Activity.RESULT_OK) {
Analyzer.log(PurchaseFinished.create(data!!))
}
}
else -> {
val position = ((requestCode and 0xFF00) shr 8) - 1
if (position >= 0) {
val holder = recyclerView.findViewHolderForLayoutPosition(position) as? ControllerViewHolder ?: return
val controller = holder.controller as? BaseItemViewController ?: return
controller.onActivityResult(requestCode and 0xFF, resultCode, data)
}
}
}
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
super.onCreateOptionsMenu(menu)
menuInflater.inflate(R.menu.menu_premium_dashboard, menu)
return true
}
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
super.onPrepareOptionsMenu(menu)
val promotionsEnabled = preferences[promotionsEnabledKey]
menu.setItemAvailability(R.id.enable_promotions, BuildConfig.DEBUG && !promotionsEnabled)
menu.setItemAvailability(R.id.disable_promotions, promotionsEnabled)
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
NavUtils.navigateUpFromSameTask(this)
}
R.id.consume_purchase -> {
if (!BuildConfig.DEBUG) {
return true
}
val weakThis = WeakReference(this)
val recreate = AtomicBoolean()
executeAfterFragmentResumed {
ProgressDialogFragment.show(it.supportFragmentManager, "consume_purchase_progress")
} and task {
val activity = weakThis.get() ?: throw IllegalStateException()
if (!activity.extraFeaturesService.destroyPurchase()) {
throw IllegalStateException()
}
}.successUi {
recreate.set(true)
}.failUi {
val activity = weakThis.get() ?: return@failUi
Toast.makeText(activity, R.string.message_unable_to_consume_purchase, Toast.LENGTH_SHORT).show()
}.alwaysUi {
weakThis.get()?.executeAfterFragmentResumed {
val fm = weakThis.get()?.supportFragmentManager
val df = fm?.findFragmentByTag("consume_purchase_progress") as? DialogFragment
df?.dismiss()
if (recreate.get()) {
weakThis.get()?.recreate()
}
}
}
}
R.id.enable_promotions -> {
preferences[promotionsEnabledKey] = true
recreate()
}
R.id.disable_promotions -> {
preferences[promotionsEnabledKey] = false
recreate()
}
}
return true
}
fun startActivityForControllerResult(intent: Intent, position: Int, requestCode: Int) {
if (position + 1 > 0xFF || requestCode > 0xFF) throw IllegalArgumentException()
startActivityForResult(intent, ((position + 1) shl 8) or requestCode)
}
class ControllerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val containerView by lazy { itemView.containerView }
var controller: ContainerView.ViewController?
get() = containerView.viewController
set(value) {
containerView.viewController = value
}
}
abstract class BaseItemViewController : ContainerView.ViewController() {
@Inject
protected lateinit var extraFeaturesService: ExtraFeaturesService
@Inject
protected lateinit var preferences: SharedPreferences
@Inject
protected lateinit var scheduleProviderFactory: StatusScheduleProvider.Factory
@Inject
protected lateinit var promotionService: PromotionService
var position: Int = RecyclerView.NO_POSITION
internal set
open val useCardBackground: Boolean = true
protected val activity: PremiumDashboardActivity get() = context as PremiumDashboardActivity
override fun onCreate() {
super.onCreate()
GeneralComponent.get(context).inject(this)
}
open fun onPause() {}
open fun onResume() {}
open fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {}
}
open class ExtraFeatureViewController : BaseItemViewController() {
protected val titleView: TextView by lazy { view.findViewById<TextView>(R.id.title) }
protected val messageView: TextView by lazy { view.findViewById<TextView>(R.id.message) }
protected val button1: Button by lazy { view.findViewById<Button>(R.id.button1) }
protected val button2: Button by lazy { view.findViewById<Button>(R.id.button2) }
override fun onCreateView(parent: ContainerView): View {
return LayoutInflater.from(parent.context).inflate(R.layout.layout_controller_extra_feature,
parent, false)
}
}
class ControllersAdapter(
context: Context,
requestManager: RequestManager
) : BaseRecyclerViewAdapter<ControllerViewHolder>(context, requestManager) {
init {
setHasStableIds(true)
}
var controllers: List<Class<out ContainerView.ViewController>>? = null
set(value) {
field = value
notifyDataSetChanged()
}
override fun getItemCount(): Int {
return controllers?.size ?: 0
}
override fun onBindViewHolder(holder: ControllerViewHolder, position: Int) {
val controller = controllers!![position].newInstance()
if (controller is BaseItemViewController) {
controller.position = holder.layoutPosition
}
holder.controller = controller
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ControllerViewHolder {
return ControllerViewHolder(LayoutInflater.from(parent.context).inflate(when (viewType) {
VIEW_TYPE_NO_CARD -> R.layout.adapter_item_extra_feature_nocard
else -> R.layout.adapter_item_extra_feature_normal
}, parent, false))
}
override fun getItemViewType(position: Int): Int {
val controller = controllers!![position].newInstance()
if (controller is BaseItemViewController) {
if (!controller.useCardBackground) {
return VIEW_TYPE_NO_CARD
}
}
return VIEW_TYPE_NORMAL
}
override fun getItemId(position: Int): Long {
return System.identityHashCode(controllers!![position]).toLong()
}
companion object {
private const val VIEW_TYPE_NORMAL = 1
private const val VIEW_TYPE_NO_CARD = 2
}
}
}