removed fragments for twitter cards

This commit is contained in:
Mariotaku Lee 2017-01-25 12:00:13 +08:00
parent 1fa6f65136
commit e3ea51dedd
No known key found for this signature in database
GPG Key ID: 15C10F89D7C33535
16 changed files with 393 additions and 434 deletions

View File

@ -1,16 +0,0 @@
package org.mariotaku.twidere.util
import android.support.test.runner.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
/**
* Created by mariotaku on 2016/12/15.
*/
@RunWith(AndroidJUnit4::class)
class TwitterCardFragmentFactoryTest {
@Test
fun testGetInstance() {
TwitterCardFragmentFactory.instance
}
}

View File

@ -1 +0,0 @@
org.mariotaku.twidere.util.TwitterCardFragmentFactoryImpl

View File

@ -1,79 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util
import android.net.Uri
import android.support.v4.app.Fragment
import com.google.android.youtube.player.YouTubeInitializationResult
import com.google.android.youtube.player.YouTubePlayer
import com.google.android.youtube.player.YouTubePlayerSupportFragment
import org.mariotaku.twidere.model.ParcelableCardEntity
import org.mariotaku.twidere.model.util.ParcelableCardEntityUtils
/**
* Created by mariotaku on 15/1/1.
*/
class TwitterCardFragmentFactoryImpl : TwitterCardFragmentFactory() {
override fun createAnimatedGifFragment(card: ParcelableCardEntity): Fragment? {
return null
}
override fun createAudioFragment(card: ParcelableCardEntity): Fragment? {
return null
}
override fun createPlayerFragment(card: ParcelableCardEntity): Fragment? {
if (java.lang.Boolean.parseBoolean("true")) return null
val appUrlResolved = ParcelableCardEntityUtils.getString(card, "app_url_resolved")
val domain = ParcelableCardEntityUtils.getString(card, "domain")
if (domain != null && appUrlResolved != null) {
val uri = Uri.parse(appUrlResolved)
val paramV = uri.getQueryParameter("v")
if ("www.youtube.com" == domain && paramV != null) {
val fragment = YouTubePlayerSupportFragment.newInstance()
fragment.initialize(YOUTUBE_DATA_API_KEY, object : YouTubePlayer.OnInitializedListener {
override fun onInitializationSuccess(provider: YouTubePlayer.Provider, player: YouTubePlayer, wasRestored: Boolean) {
if (!wasRestored) {
player.cueVideo(paramV)
}
}
override fun onInitializationFailure(provider: YouTubePlayer.Provider, errorReason: YouTubeInitializationResult) {
val activity = fragment.activity ?: return
// if (errorReason.isUserRecoverableError()) {
// errorReason.getErrorDialog(activity, RECOVERY_DIALOG_REQUEST).show();
// } else {
// Toast.makeText(activity, errorReason.toString(), Toast.LENGTH_LONG).show();
// }
}
})
return fragment
}
}
return null
}
companion object {
private val YOUTUBE_DATA_API_KEY = "AIzaSyCVdCIMFFxdNqHnCPrJ9yKUzoTfs8jhYGc"
}
}

View File

@ -1 +1 @@
org.mariotaku.twidere.util.TwitterCardFragmentFactoryImpl
TwitterCardViewFactoryImpl

View File

@ -1,72 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import org.mariotaku.twidere.util.support.ViewSupport;
/**
* Created by mariotaku on 15/1/1.
*/
public class TwitterCardContainer extends FrameLayout {
private int mCardWidth, mCardHeight;
public TwitterCardContainer(Context context) {
super(context);
}
public TwitterCardContainer(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TwitterCardContainer(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setCardSize(int width, int height) {
mCardWidth = width;
mCardHeight = height;
if (!ViewSupport.isInLayout(this)) {
requestLayout();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (mCardWidth <= 0 || mCardHeight <= 0) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
final int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
final int measuredHeight = Math.round(measuredWidth * (mCardHeight / (float) mCardWidth));
final int newWidthMeasureSpec = MeasureSpec.makeMeasureSpec(measuredWidth, MeasureSpec.EXACTLY);
final int newHeightMeasureSpec;
if (measuredHeight != 0) {
newHeightMeasureSpec = MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY);
} else {
newHeightMeasureSpec = heightMeasureSpec;
}
super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec);
}
}

View File

@ -31,7 +31,6 @@ import android.nfc.NfcAdapter.CreateNdefMessageCallback
import android.os.AsyncTask
import android.os.Bundle
import android.support.annotation.UiThread
import android.support.v4.app.FragmentManagerAccessor
import android.support.v4.app.LoaderManager.LoaderCallbacks
import android.support.v4.app.hasRunningLoadersSafe
import android.support.v4.content.AsyncTaskLoader
@ -106,6 +105,7 @@ import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.ContentScrollHandler.ContentListSupport
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback
import org.mariotaku.twidere.util.RecyclerViewScrollHandler.RecyclerViewCallback
import org.mariotaku.twidere.util.twitter.card.TwitterCardViewFactory
import org.mariotaku.twidere.view.CardMediaContainer.OnMediaClickListener
import org.mariotaku.twidere.view.ExtendedRecyclerView
import org.mariotaku.twidere.view.holder.GapViewHolder
@ -996,24 +996,25 @@ class StatusFragment : BaseFragment(), LoaderCallbacks<SingleResponse<Parcelable
itemView.mediaPreview.displayMedia()
}
val fm = fragment.childFragmentManager
if (TwitterCardUtils.isCardSupported(status)) {
val size = TwitterCardUtils.getCardSize(status.card!!)
itemView.twitterCard.visibility = View.VISIBLE
if (size != null) {
itemView.twitterCard.setCardSize(size.x, size.y)
} else {
itemView.twitterCard.setCardSize(0, 0)
}
val cardFragment = TwitterCardFragmentFactory.createCardFragment(status)
val fm = fragment.childFragmentManager
if (cardFragment != null && !FragmentManagerAccessor.isStateSaved(fm)) {
val ft = fm.beginTransaction()
ft.replace(R.id.twitterCard, cardFragment)
ft.commit()
val vc = TwitterCardViewFactory.from(status)
itemView.twitterCard.viewController = vc
if (vc != null) {
itemView.twitterCard.visibility = View.VISIBLE
} else {
itemView.twitterCard.visibility = View.GONE
}
} else {
itemView.twitterCard.viewController = null
itemView.twitterCard.visibility = View.GONE
}

View File

@ -1,49 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.fragment.card
import android.os.Bundle
import org.mariotaku.twidere.Constants.EXTRA_URI
import org.mariotaku.twidere.fragment.BrowserFragment
/**
* Created by mariotaku on 15/1/6.
*/
class CardBrowserFragment : BrowserFragment() {
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
val settings = webView!!.settings
settings.builtInZoomControls = false
}
companion object {
fun show(uri: String, extraArgs: Bundle?): CardBrowserFragment {
val args = Bundle()
args.putString(EXTRA_URI, uri)
if (extraArgs != null) {
args.putAll(extraArgs)
}
val fragment = CardBrowserFragment()
fragment.arguments = args
return fragment
}
}
}

View File

@ -1,81 +0,0 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util
import android.os.Bundle
import android.support.v4.app.Fragment
import org.mariotaku.twidere.fragment.card.CardBrowserFragment
import org.mariotaku.twidere.fragment.card.CardPollFragment
import org.mariotaku.twidere.model.ParcelableCardEntity
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.util.ParcelableCardEntityUtils
import java.util.*
/**
* Created by mariotaku on 15/1/1.
*/
abstract class TwitterCardFragmentFactory {
abstract fun createAnimatedGifFragment(card: ParcelableCardEntity): Fragment?
abstract fun createAudioFragment(card: ParcelableCardEntity): Fragment?
abstract fun createPlayerFragment(card: ParcelableCardEntity): Fragment?
companion object {
val instance: TwitterCardFragmentFactory by lazy {
ServiceLoader.load(TwitterCardFragmentFactory::class.java).first()
}
fun createGenericPlayerFragment(card: ParcelableCardEntity?, args: Bundle?): Fragment? {
if (card == null) return null
val playerUrl = ParcelableCardEntityUtils.getString(card, "player_url") ?: return null
return CardBrowserFragment.show(playerUrl, args)
}
fun createCardPollFragment(status: ParcelableStatus): Fragment {
return CardPollFragment.show(status)
}
fun createCardFragment(status: ParcelableStatus): Fragment? {
val card = status.card
if (card == null || card.name == null) return null
if (TwitterCardUtils.CARD_NAME_PLAYER == card.name) {
val playerFragment = instance.createPlayerFragment(card)
if (playerFragment != null) return playerFragment
return TwitterCardFragmentFactory.createGenericPlayerFragment(card, null)
} else if (TwitterCardUtils.CARD_NAME_AUDIO == card.name) {
val playerFragment = instance.createAudioFragment(card)
if (playerFragment != null) return playerFragment
return TwitterCardFragmentFactory.createGenericPlayerFragment(card, null)
} else if (TwitterCardUtils.CARD_NAME_ANIMATED_GIF == card.name) {
val playerFragment = instance.createAnimatedGifFragment(card)
if (playerFragment != null) return playerFragment
return TwitterCardFragmentFactory.createGenericPlayerFragment(card, null)
} else if (TwitterCardUtils.isPoll(card)) {
return TwitterCardFragmentFactory.createCardPollFragment(status)
}
return null
}
}
}

View File

@ -0,0 +1,76 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.util.twitter.card
import org.mariotaku.twidere.model.ParcelableCardEntity
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.util.ParcelableCardEntityUtils
import org.mariotaku.twidere.util.TwitterCardUtils
import org.mariotaku.twidere.view.ContainerView
import org.mariotaku.twidere.view.controller.twitter.card.CardBrowserViewController
import org.mariotaku.twidere.view.controller.twitter.card.CardPollViewController
import java.util.*
/**
* Created by mariotaku on 15/1/1.
*/
abstract class TwitterCardViewFactory {
abstract fun from(status: ParcelableStatus): ContainerView.ViewController?
companion object {
fun from(status: ParcelableStatus): ContainerView.ViewController? {
val vc = fromImplementations(status)
if (vc != null) return vc
return createCardFragment(status)
}
private fun fromImplementations(status: ParcelableStatus): ContainerView.ViewController? {
ServiceLoader.load(TwitterCardViewFactory::class.java).forEach { factory ->
val vc = factory.from(status)
if (vc != null) return vc
}
return null
}
private fun createCardFragment(status: ParcelableStatus): ContainerView.ViewController? {
val card = status.card
if (card == null || card.name == null) return null
if (TwitterCardUtils.CARD_NAME_PLAYER == card.name) {
return createGenericPlayerFragment(card)
} else if (TwitterCardUtils.CARD_NAME_AUDIO == card.name) {
return createGenericPlayerFragment(card)
} else if (TwitterCardUtils.isPoll(card)) {
return createCardPollFragment(status)
}
return null
}
private fun createCardPollFragment(status: ParcelableStatus): ContainerView.ViewController {
return CardPollViewController.show(status)
}
private fun createGenericPlayerFragment(card: ParcelableCardEntity): ContainerView.ViewController? {
val playerUrl = ParcelableCardEntityUtils.getString(card, "player_url") ?: return null
return CardBrowserViewController.show(playerUrl)
}
}
}

View File

@ -0,0 +1,16 @@
package org.mariotaku.twidere.util.twitter.card.impl
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.util.twitter.card.TwitterCardViewFactory
import org.mariotaku.twidere.view.ContainerView
/**
* Created by mariotaku on 2017/1/25.
*/
class DefaultTwitterCardViewFactory : TwitterCardViewFactory() {
override fun from(status: ParcelableStatus): ContainerView.ViewController? {
return null
}
}

View File

@ -0,0 +1,96 @@
package org.mariotaku.twidere.view
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.FrameLayout
/**
* Created by mariotaku on 2017/1/25.
*/
open class ContainerView(context: Context, attrs: AttributeSet? = null) : FrameLayout(context, attrs) {
private var attachedToWindow: Boolean = false
var viewController: ViewController? = null
set(vc) {
field?.let { vc ->
if (vc.attached) {
vc.attached = false
vc.onDetached()
}
val view = vc.view
vc.onDestroyView(view)
this.removeView(view)
vc.onDestroy()
}
field = vc
if (vc != null) {
if (vc.attached) {
throw IllegalStateException("ViewController has already attached")
}
vc.context = context
val view = vc.onCreateView(this)
this.addView(view)
vc.view = view
vc.onCreate()
vc.onViewCreated(view)
if (attachedToWindow) {
vc.attached = true
vc.onAttached()
}
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
attachedToWindow = true
viewController?.let { vc ->
if (!vc.windowAttached) {
vc.windowAttached = true
vc.onWindowAttached()
}
}
}
override fun onDetachedFromWindow() {
attachedToWindow = false
viewController?.let { vc ->
if (vc.attached) {
vc.windowAttached = false
vc.onWindowDetached()
}
}
super.onDetachedFromWindow()
}
abstract class ViewController {
lateinit var context: Context
internal set
lateinit var view: View
internal set
var attached: Boolean = false
internal set
var windowAttached: Boolean = false
internal set
open fun onCreate() {}
open fun onDestroy() {}
open fun onAttached() {}
open fun onDetached() {}
open fun onWindowAttached() {}
open fun onWindowDetached() {}
abstract fun onCreateView(parent: ContainerView): View
open fun onDestroyView(view: View) {}
open fun onViewCreated(view: View) {}
}
}

View File

@ -0,0 +1,59 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.view
import android.content.Context
import android.util.AttributeSet
import android.view.View
import org.mariotaku.twidere.util.support.ViewSupport
/**
* Created by mariotaku on 15/1/1.
*/
class TwitterCardContainer(context: Context, attrs: AttributeSet? = null) : ContainerView(context, attrs) {
private var cardWidth: Int = 0
private var cardHeight: Int = 0
fun setCardSize(width: Int, height: Int) {
cardWidth = width
cardHeight = height
if (!ViewSupport.isInLayout(this)) {
requestLayout()
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
if (cardWidth <= 0 || cardHeight <= 0) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
return
}
val measuredWidth = View.MeasureSpec.getSize(widthMeasureSpec)
val measuredHeight = Math.round(measuredWidth * (cardHeight / cardWidth.toFloat()))
val newWidthMeasureSpec = View.MeasureSpec.makeMeasureSpec(measuredWidth, View.MeasureSpec.EXACTLY)
val newHeightMeasureSpec: Int
if (measuredHeight != 0) {
newHeightMeasureSpec = View.MeasureSpec.makeMeasureSpec(measuredHeight, View.MeasureSpec.EXACTLY)
} else {
newHeightMeasureSpec = heightMeasureSpec
}
super.onMeasure(newWidthMeasureSpec, newHeightMeasureSpec)
}
}

View File

@ -0,0 +1,68 @@
/*
* Twidere - Twitter client for Android
*
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.view.controller.twitter.card
import android.annotation.SuppressLint
import android.view.View
import android.view.ViewGroup
import android.webkit.WebView
import android.widget.FrameLayout
import org.mariotaku.twidere.view.ContainerView
/**
* Created by mariotaku on 15/1/6.
*/
class CardBrowserViewController : ContainerView.ViewController() {
lateinit var url: String
override fun onCreateView(parent: ContainerView): View {
val webView = WebView(context)
webView.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT)
return webView
}
override fun onDestroyView(view: View) {
(view as WebView).destroy()
super.onDestroyView(view)
}
@SuppressLint("SetJavaScriptEnabled")
override fun onCreate() {
super.onCreate()
val webView = view as WebView
webView.settings.apply {
javaScriptEnabled = true
builtInZoomControls = false
}
webView.loadUrl(url)
}
companion object {
fun show(url: String): CardBrowserViewController {
val vc = CardBrowserViewController()
vc.url = url
return vc
}
}
}

View File

@ -17,39 +17,30 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.mariotaku.twidere.fragment.card
package org.mariotaku.twidere.view.controller.twitter.card
import android.accounts.AccountManager
import android.content.Context
import android.graphics.*
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.support.v4.app.LoaderManager
import android.support.v4.content.AsyncTaskLoader
import android.support.v4.content.ContextCompat
import android.support.v4.content.Loader
import android.text.format.DateUtils
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.RadioButton
import android.widget.TextView
import kotlinx.android.synthetic.main.fragment_card_poll.*
import kotlinx.android.synthetic.main.layout_twitter_card_poll.view.*
import nl.komponents.kovenant.task
import nl.komponents.kovenant.ui.successUi
import org.apache.commons.lang3.math.NumberUtils
import org.mariotaku.abstask.library.AbstractTask
import org.mariotaku.abstask.library.TaskStarter
import org.mariotaku.microblog.library.MicroBlogException
import org.mariotaku.microblog.library.twitter.TwitterCaps
import org.mariotaku.microblog.library.twitter.model.CardDataMap
import org.mariotaku.twidere.Constants.EXTRA_CARD
import org.mariotaku.twidere.Constants.LOGTAG
import org.mariotaku.twidere.R
import org.mariotaku.twidere.constant.IntentConstants
import org.mariotaku.twidere.constant.IntentConstants.EXTRA_STATUS
import org.mariotaku.twidere.extension.model.newMicroBlogInstance
import org.mariotaku.twidere.fragment.BaseFragment
import org.mariotaku.twidere.model.AccountDetails
import org.mariotaku.twidere.model.ParcelableCardEntity
import org.mariotaku.twidere.model.ParcelableStatus
import org.mariotaku.twidere.model.util.AccountUtils
@ -57,46 +48,70 @@ import org.mariotaku.twidere.model.util.ParcelableCardEntityUtils
import org.mariotaku.twidere.util.MicroBlogAPIFactory
import org.mariotaku.twidere.util.TwitterCardUtils
import org.mariotaku.twidere.util.support.ViewSupport
import org.mariotaku.twidere.view.ContainerView
import java.lang.ref.WeakReference
import java.util.*
/**
* Created by mariotaku on 15/12/20.
*/
class CardPollFragment : BaseFragment(), LoaderManager.LoaderCallbacks<ParcelableCardEntity?>, View.OnClickListener {
class CardPollViewController : ContainerView.ViewController() {
private lateinit var status: ParcelableStatus
private var fetchedCard: ParcelableCardEntity? = null
private val card: ParcelableCardEntity
get() = fetchedCard ?: status.card!!
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
initChoiceView(savedInstanceState)
loaderManager.initLoader(0, null, this)
override fun onCreate() {
super.onCreate()
initChoiceView()
loadCardPoll()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return inflater.inflate(R.layout.fragment_card_poll, container, false)
override fun onCreateView(parent: ContainerView): View {
return LayoutInflater.from(context).inflate(R.layout.layout_twitter_card_poll, parent, false)
}
override fun fitSystemWindows(insets: Rect) {
// No-op
}
private fun initChoiceView(savedInstanceState: Bundle?) {
val card = card
val status = status
private fun initChoiceView() {
val choicesCount = TwitterCardUtils.getChoicesCount(card)
val inflater = getLayoutInflater(savedInstanceState)
val inflater = LayoutInflater.from(context)
for (i in 0 until choicesCount) {
inflater.inflate(R.layout.layout_poll_item, pollContainer, true)
inflater.inflate(R.layout.layout_poll_item, view.pollContainer, true)
}
displayPoll(card, status)
}
private fun displayAndReloadPoll(result: ParcelableCardEntity, status: ParcelableStatus) {
if (!attached) return
displayPoll(result, status)
loadCardPoll()
}
private fun loadCardPoll() {
val weakThis = WeakReference(this)
task {
val vc = weakThis.get() ?: throw IllegalStateException()
val card = vc.card
val details = AccountUtils.getAccountDetails(AccountManager.get(vc.context), card.account_key, true)!!
val caps = details.newMicroBlogInstance(vc.context, cls = TwitterCaps::class.java)
val params = CardDataMap()
params.putString("card_uri", card.url)
params.putString("cards_platform", MicroBlogAPIFactory.CARDS_PLATFORM_ANDROID_12)
params.putString("response_card_name", card.name)
val cardResponse = caps.getPassThrough(params).card
if (cardResponse == null || cardResponse.name == null) {
throw IllegalStateException()
}
return@task ParcelableCardEntityUtils.fromCardEntity(cardResponse, details.key)
}.successUi { data ->
weakThis.get()?.displayPoll(data, status)
}
}
private fun displayPoll(card: ParcelableCardEntity?, status: ParcelableStatus?) {
val context = context
if (card == null || status == null || context == null) return
if (card == null || status == null) return
fetchedCard = card
val choicesCount = TwitterCardUtils.getChoicesCount(card)
var votesSum = 0
@ -116,8 +131,8 @@ class CardPollFragment : BaseFragment(), LoaderManager.LoaderCallbacks<Parcelabl
override fun onClick(v: View) {
if (hasChoice || clickedChoice) return
for (i in 0 until pollContainer.childCount) {
val pollItem = pollContainer.getChildAt(i)
for (i in 0 until view.pollContainer.childCount) {
val pollItem = view.pollContainer.getChildAt(i)
pollItem.isClickable = false
clickedChoice = true
val choiceRadioButton = pollItem.findViewById(R.id.choice_button) as RadioButton
@ -130,9 +145,9 @@ class CardPollFragment : BaseFragment(), LoaderManager.LoaderCallbacks<Parcelabl
cardData.putString("cards_platform", MicroBlogAPIFactory.CARDS_PLATFORM_ANDROID_12)
cardData.putString("response_card_name", card.name)
cardData.putString("selected_choice", (i + 1).toString())
val task = object : AbstractTask<CardDataMap, ParcelableCardEntity, CardPollFragment>() {
val task = object : AbstractTask<CardDataMap, ParcelableCardEntity, CardPollViewController>() {
public override fun afterExecute(handler: CardPollFragment?, result: ParcelableCardEntity?) {
public override fun afterExecute(handler: CardPollViewController?, result: ParcelableCardEntity?) {
result ?: return
handler?.displayAndReloadPoll(result, status)
}
@ -152,7 +167,7 @@ class CardPollFragment : BaseFragment(), LoaderManager.LoaderCallbacks<Parcelabl
return null
}
}
task.callback = this@CardPollFragment
task.callback = this@CardPollViewController
task.params = cardData
TaskStarter.execute(task)
}
@ -161,9 +176,9 @@ class CardPollFragment : BaseFragment(), LoaderManager.LoaderCallbacks<Parcelabl
}
val color = ContextCompat.getColor(context, R.color.material_light_blue_a200)
val radius = resources.getDimension(R.dimen.element_spacing_small)
val radius = context.resources.getDimension(R.dimen.element_spacing_small)
for (i in 0..choicesCount - 1) {
val pollItem = pollContainer.getChildAt(i)
val pollItem = view.pollContainer.getChildAt(i)
val choicePercentView = pollItem.findViewById(R.id.choice_percent) as TextView
val choiceLabelView = pollItem.findViewById(R.id.choice_label) as TextView
@ -196,48 +211,10 @@ class CardPollFragment : BaseFragment(), LoaderManager.LoaderCallbacks<Parcelabl
}
val nVotes = resources.getQuantityString(R.plurals.N_votes, votesSum, votesSum)
val nVotes = context.resources.getQuantityString(R.plurals.N_votes, votesSum, votesSum)
val timeLeft = DateUtils.getRelativeTimeSpanString(context, endDatetimeUtc.time, true)
pollSummary.text = getString(R.string.poll_summary_format, nVotes, timeLeft)
}
private fun displayAndReloadPoll(result: ParcelableCardEntity, status: ParcelableStatus) {
if (host == null) return
displayPoll(result, status)
loaderManager.restartLoader(0, null, this)
}
private val card: ParcelableCardEntity
get() {
val fetched = fetchedCard
if (fetched != null) return fetched
val card = arguments.getParcelable<ParcelableCardEntity>(EXTRA_CARD)!!
assert(card.name != null)
return card
}
private val status: ParcelableStatus
get() = arguments.getParcelable<ParcelableStatus>(EXTRA_STATUS)
override fun onClick(v: View) {
}
override fun onCreateLoader(id: Int, args: Bundle?): Loader<ParcelableCardEntity?> {
val card = card
val details = AccountUtils.getAccountDetails(AccountManager.get(context), card.account_key, true)!!
return ParcelableCardEntityLoader(context, details, card.url, card.name)
}
override fun onLoadFinished(loader: Loader<ParcelableCardEntity?>, data: ParcelableCardEntity?) {
if (data == null) return
displayPoll(data, status)
}
override fun onLoaderReset(loader: Loader<ParcelableCardEntity?>) {
view.pollSummary.text = context.getString(R.string.poll_summary_format, nVotes, timeLeft)
}
private class PercentDrawable internal constructor(
@ -246,22 +223,18 @@ class CardPollFragment : BaseFragment(), LoaderManager.LoaderCallbacks<Parcelabl
color: Int
) : Drawable() {
private val mPaint: Paint
private val mBounds: RectF
init {
mPaint = Paint(Paint.ANTI_ALIAS_FLAG)
mPaint.color = color
mBounds = RectF()
private val paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
this.color = color
}
private val boundsF: RectF = RectF()
override fun draw(canvas: Canvas) {
canvas.drawRoundRect(mBounds, radius, radius, mPaint)
canvas.drawRoundRect(boundsF, radius, radius, paint)
}
override fun onBoundsChange(bounds: Rect) {
mBounds.set(bounds)
mBounds.right = mBounds.left + mBounds.width() * percent
boundsF.set(bounds)
boundsF.right = boundsF.left + boundsF.width() * percent
super.onBoundsChange(bounds)
}
@ -278,45 +251,12 @@ class CardPollFragment : BaseFragment(), LoaderManager.LoaderCallbacks<Parcelabl
}
}
class ParcelableCardEntityLoader(
context: Context,
private val details: AccountDetails,
private val cardUri: String,
private val cardName: String
) : AsyncTaskLoader<ParcelableCardEntity?>(context) {
override fun loadInBackground(): ParcelableCardEntity? {
val caps = details.newMicroBlogInstance(context, cls = TwitterCaps::class.java)
try {
val params = CardDataMap()
params.putString("card_uri", cardUri)
params.putString("cards_platform", MicroBlogAPIFactory.CARDS_PLATFORM_ANDROID_12)
params.putString("response_card_name", cardName)
val card = caps.getPassThrough(params).card
if (card == null || card.name == null) {
return null
}
return ParcelableCardEntityUtils.fromCardEntity(card, details.key)
} catch (e: MicroBlogException) {
return null
}
}
override fun onStartLoading() {
forceLoad()
}
}
companion object {
fun show(status: ParcelableStatus): CardPollFragment {
val fragment = CardPollFragment()
val args = Bundle()
args.putParcelable(EXTRA_STATUS, status)
args.putParcelable(IntentConstants.EXTRA_CARD, status.card)
fragment.arguments = args
return fragment
fun show(status: ParcelableStatus): CardPollViewController {
val vc = CardPollViewController()
vc.status = status
return vc
}
}

View File

@ -0,0 +1 @@
org.mariotaku.twidere.util.twitter.card.impl.DefaultTwitterCardViewFactory