removed fragments for twitter cards
This commit is contained in:
parent
1fa6f65136
commit
e3ea51dedd
|
@ -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
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
org.mariotaku.twidere.util.TwitterCardFragmentFactoryImpl
|
|
@ -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"
|
||||
}
|
||||
|
||||
}
|
|
@ -1 +1 @@
|
|||
org.mariotaku.twidere.util.TwitterCardFragmentFactoryImpl
|
||||
TwitterCardViewFactoryImpl
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
|
@ -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) {}
|
||||
}
|
||||
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.mariotaku.twidere.util.twitter.card.impl.DefaultTwitterCardViewFactory
|
Loading…
Reference in New Issue